<?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=Philip+Dames</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=Philip+Dames"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/Philip_Dames"/>
	<updated>2026-04-19T18:22:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19031</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19031"/>
		<updated>2010-09-05T17:20:38Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Experiment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setting up the Junus Amplifier =&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.png|thumb|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, use the USB to RS-232 cable to connect the amp to your PC.  If this doesn&amp;#039;t work you will need to find and install the driver for the HL-340 USB to serial converter (there is a copy of the driver in the folder Philip&amp;#039;s Files\usb-serial-driver.zip on the desktop of the PC used for the QNX manipulation project).  You will also need to download and install [http://www.copleycontrols.com/Motion/Downloads/index.html CME2] (Copley Motion Explorer); note that Copley&amp;#039;s documentation for the amplifier and software can also be downloaded from the same page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:copley_basic_setup.png|thumb|Basic Setup Menu|right]]&lt;br /&gt;
Open the program and add the COM port used by the USB to serial cable to the list (the list can be changed later in the Tools -&amp;gt; Communication Wizard menu).  Next go to Amplifier -&amp;gt; Basic Setup.  Here you select from the different operational modes and input types.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating Modes ==&lt;br /&gt;
* Current - This is the most commonly used mode.  Here, the amplifier will create an output current proportional to some input signal to drive the attached actuator.  In this mode there is only one control loop running within the amplifier making it the preferred choice (the more control that can be done outside the amp, the less of a black box it is).&lt;br /&gt;
* Velocity - This mode takes the current control mode and adds another feedback loop around the current control loop so that the velocity of the motor is proportional to the input signal.  For the Junus amps, the motor speed is estimated from the back emf of the motor during use, making it less reliable than the current control mode.&lt;br /&gt;
&lt;br /&gt;
== Command Sources ==&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:junus_amp_pin_diagram.png|thumb|Junus Amp Input Pin Diagram|right]]&lt;br /&gt;
The pin diagram for the Junus amp is found to the right.&lt;br /&gt;
* Analog Command - In this mode, an analog input is connected to pins 2 and 9, with the analog reference voltage going to pin 9 and the signal going to pin 2.  The voltage range for the input is +/- 10V with the output being proportional to the voltage, i.e. 0V is 0A (or 0rpm) output, +10V is maximum positive current output, and -10V is maximum negative current output.&lt;br /&gt;
* PWM Command - In this mode the output is related to the duty cycle of the PWM signal in one of two ways.  To switch between these modes, click on the PWM command button in the block diagram.&lt;br /&gt;
** 50% mode - This mode uses a single input pin (pin 3).  Here a 50% duty cycle is the zero point (0A or 0rpm) with 0% being fully negative and 100% being fully positive.&lt;br /&gt;
** 100% mode - In addition to the PWM input pin there is an extra input pin (pin 4) to control the sign (or direction) of the output.  Here, a 0% duty cycle is the zero point, 100% duty cycle with the direction pin LO is fully negative and 100% duty cycle with the direction pin HI is fully positive.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now click on the Motor button in the block diagram.  Here you can input all the necessary parameters about your motor from the data sheet, or that you experimentally found.  Now you are ready to look at the control loop.  There is a PI controller with tunable parameters used to control the output current.  While you are welcome to play around with the parameters on your own, I would suggest that you click on the I Loop button and select Auto Tune, at least to get a starting point for the parameters.  It will give you several options based on different levels of aggressiveness of the controller.&lt;br /&gt;
&lt;br /&gt;
Click on Input/Output.  Here you can set up the different input and output pins.  I recommend using IN1 as Amp Enable-HI (or LO) Enables With Clear Faults (pin 13).  This ensures that the motor can only spin when you give it a command to turn on.  Choose HI if your digital outputs default to LO, or vice versa, as it can vary depending on the presence of pull-up resistors, etc.  You now have your amp configured and you are ready to start controlling your motor.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of other utilities built into the CME2 software.  The first is the Control Panel (second button from the left in the top menu).  This allows you to software enable/disable the amplifier as well as monitor various inputs/outputs of the motor during use.  The other is the Scope (third button from the left in the top menu).  This lets you apply various functions to drive the motor and monitor inputs/outputs over time.  This is useful for making sure your control parameters are tuned the way you like them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Using the Motor =&lt;br /&gt;
&lt;br /&gt;
If you are using analog command mode, a simple test to make sure your setup is working correctly is to connect the enable pin to +5V (or GND, depending on how it was configured) and use a potentiometer to control the input voltage and make sure the motor spins as you would expect it to.  As a reminder, 0V is 0 output, negative voltage will move it in one direction and positive voltage in the other.&lt;br /&gt;
&lt;br /&gt;
If you are using PWM command mode, a more involved test would be to do the activity found [[ME 333 Lab 4 | here]].  For our system, the plant would be the entire amp/motor package and feedback loop in the diagram at the top is designed to control the position of the motor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Motor Modeling =&lt;br /&gt;
&lt;br /&gt;
For our purposes, we have chosen to model the motor using the following equation, where &amp;lt;math&amp;gt;\tau&amp;lt;/math&amp;gt; is the output torque, &amp;lt;math&amp;gt;k_m&amp;lt;/math&amp;gt; is the motor constant, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; is the command current, &amp;lt;math&amp;gt;\mu_d&amp;lt;/math&amp;gt; is the dynamic friction coefficient, &amp;lt;math&amp;gt;mu_s&amp;lt;/math&amp;gt; is the static friction, &amp;lt;math&amp;gt;\omega&amp;lt;/math&amp;gt; is the speed of the motor, and the &amp;lt;math&amp;gt;sgn&amp;lt;/math&amp;gt; function returns the sign of its argument.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \tau = k_m i - \mu_d \omega - \mu_s sgn(\omega) \,&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be easily solved to find the necessary command current (and thus the analog or PWM input) needed to follow a reference trajectory, which would be the feedforward model of our system.&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
&lt;br /&gt;
To determine the values of the parameters in the above equation, you should run a series of tests at various input levels to make sure the parameters are constant at various speeds and accelerations of the motor.  To set up the experiment you will need a mount for the motor (a table-mount vice works well), an object of known inertia (ex. momentum wheel), and you will need to hook up the encoder on the motor to a device that can read it in (ex. decoding chip connected to a PIC).&lt;br /&gt;
&lt;br /&gt;
== Experiment ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:motor_model_wiring.png|200px|Wiring diagram for the motor modeling setup|right]]&lt;br /&gt;
For each run of the experiment, the motor is driven by three periods of a square wave current at a specified amplitude.  Multiple periods are used to allow transient behavior to die down and for filtering purposes, described in the following section.  During each run the position from the encoder is recorded and post-processing is used to find the velocity and acceleration associated with the trajectory.&lt;br /&gt;
&lt;br /&gt;
Code used to drive the motor during the experiment can be downloaded [[Media:motor_model_PIC_code.zip|here]].  This code is meant to be run on the [Introduction to the PIC32|PIC32 board].  The basic wiring diagram is to the right and the datasheet for the LS7083 decoder can be found here [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html] and includes all the wiring diagrams necessary.&lt;br /&gt;
&lt;br /&gt;
To actually run the experiment, use the MATLAB code [[Media:motor_model_analysis_code.zip|here]].  The function dataCollection takes in the amplitude of your square wave current and outputs this to the amp.  It then collects the trajectory data and saves it to a .mat file (see file for details on directory and file name format).  Note that the COM port, Imax (maximum current set on the amp), and other variables must be changed in both the MATLAB code and the amp or PIC.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:filtering_example.png|200px|An example of filtering data|right]]&lt;br /&gt;
To find the velocity and acceleration of the motor during the experiment, the raw data from the encoder must be smoothed otherwise there are large spikes in the calculated derivatives due to signal noise, etc.  To smooth the data, a moving average is used (this is why we collected extra periods of data, so we can still apply the moving average to the end points).  The idea of a moving average is the filtered value at a specific time is the average of the unfiltered value and the nearest N values in each direction.  Choosing a low N leads to less smoothing but retains more of the original data.  I found that an N of 5 was good for my data set, but this will be different for each application depending on the amount of noise, etc.  The number of points to use in the filter is the second (and optional) argument to the MATLAB file fitParameters.  In this function, the raw data is first smoothed using the moving average, then finite differences are used to calculate the velocity.  This is then smoothed using the same moving average and finite differences are used again to find the acceleration.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fitting Parameters ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:model_example.png|200px|An example of motor model data|right]]&lt;br /&gt;
Now that you have the acceleration, you can easily find the torque because you know the inertia of the object being rotated.  Going back to the model, you now have the torque and velocity so you can solve for the three unknowns.  You can also choose to model the motor as having a different set of parameters for positive and negative torques, something I found to work better than a single set of parameters.&lt;br /&gt;
&lt;br /&gt;
In the figure to the right, an example of a motor model is shown, with trials run at 50 mA intervals from 150 to 400 mA.  The filtered data is plotted as the dots and the ideal model based on the calculated parameters are the solid lines, this type of plot can be generated from the function batchProcess.  In this plot, the effect of filtering is evident in the rounded edges near the transition points (crossing zero velocity and zero acceleration lines).  You can also see the motor is reaching its maximum speed at 200 mA.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19030</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19030"/>
		<updated>2010-09-05T17:20:13Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Experiment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setting up the Junus Amplifier =&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.png|thumb|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, use the USB to RS-232 cable to connect the amp to your PC.  If this doesn&amp;#039;t work you will need to find and install the driver for the HL-340 USB to serial converter (there is a copy of the driver in the folder Philip&amp;#039;s Files\usb-serial-driver.zip on the desktop of the PC used for the QNX manipulation project).  You will also need to download and install [http://www.copleycontrols.com/Motion/Downloads/index.html CME2] (Copley Motion Explorer); note that Copley&amp;#039;s documentation for the amplifier and software can also be downloaded from the same page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:copley_basic_setup.png|thumb|Basic Setup Menu|right]]&lt;br /&gt;
Open the program and add the COM port used by the USB to serial cable to the list (the list can be changed later in the Tools -&amp;gt; Communication Wizard menu).  Next go to Amplifier -&amp;gt; Basic Setup.  Here you select from the different operational modes and input types.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating Modes ==&lt;br /&gt;
* Current - This is the most commonly used mode.  Here, the amplifier will create an output current proportional to some input signal to drive the attached actuator.  In this mode there is only one control loop running within the amplifier making it the preferred choice (the more control that can be done outside the amp, the less of a black box it is).&lt;br /&gt;
* Velocity - This mode takes the current control mode and adds another feedback loop around the current control loop so that the velocity of the motor is proportional to the input signal.  For the Junus amps, the motor speed is estimated from the back emf of the motor during use, making it less reliable than the current control mode.&lt;br /&gt;
&lt;br /&gt;
== Command Sources ==&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:junus_amp_pin_diagram.png|thumb|Junus Amp Input Pin Diagram|right]]&lt;br /&gt;
The pin diagram for the Junus amp is found to the right.&lt;br /&gt;
* Analog Command - In this mode, an analog input is connected to pins 2 and 9, with the analog reference voltage going to pin 9 and the signal going to pin 2.  The voltage range for the input is +/- 10V with the output being proportional to the voltage, i.e. 0V is 0A (or 0rpm) output, +10V is maximum positive current output, and -10V is maximum negative current output.&lt;br /&gt;
* PWM Command - In this mode the output is related to the duty cycle of the PWM signal in one of two ways.  To switch between these modes, click on the PWM command button in the block diagram.&lt;br /&gt;
** 50% mode - This mode uses a single input pin (pin 3).  Here a 50% duty cycle is the zero point (0A or 0rpm) with 0% being fully negative and 100% being fully positive.&lt;br /&gt;
** 100% mode - In addition to the PWM input pin there is an extra input pin (pin 4) to control the sign (or direction) of the output.  Here, a 0% duty cycle is the zero point, 100% duty cycle with the direction pin LO is fully negative and 100% duty cycle with the direction pin HI is fully positive.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now click on the Motor button in the block diagram.  Here you can input all the necessary parameters about your motor from the data sheet, or that you experimentally found.  Now you are ready to look at the control loop.  There is a PI controller with tunable parameters used to control the output current.  While you are welcome to play around with the parameters on your own, I would suggest that you click on the I Loop button and select Auto Tune, at least to get a starting point for the parameters.  It will give you several options based on different levels of aggressiveness of the controller.&lt;br /&gt;
&lt;br /&gt;
Click on Input/Output.  Here you can set up the different input and output pins.  I recommend using IN1 as Amp Enable-HI (or LO) Enables With Clear Faults (pin 13).  This ensures that the motor can only spin when you give it a command to turn on.  Choose HI if your digital outputs default to LO, or vice versa, as it can vary depending on the presence of pull-up resistors, etc.  You now have your amp configured and you are ready to start controlling your motor.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of other utilities built into the CME2 software.  The first is the Control Panel (second button from the left in the top menu).  This allows you to software enable/disable the amplifier as well as monitor various inputs/outputs of the motor during use.  The other is the Scope (third button from the left in the top menu).  This lets you apply various functions to drive the motor and monitor inputs/outputs over time.  This is useful for making sure your control parameters are tuned the way you like them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Using the Motor =&lt;br /&gt;
&lt;br /&gt;
If you are using analog command mode, a simple test to make sure your setup is working correctly is to connect the enable pin to +5V (or GND, depending on how it was configured) and use a potentiometer to control the input voltage and make sure the motor spins as you would expect it to.  As a reminder, 0V is 0 output, negative voltage will move it in one direction and positive voltage in the other.&lt;br /&gt;
&lt;br /&gt;
If you are using PWM command mode, a more involved test would be to do the activity found [[ME 333 Lab 4 | here]].  For our system, the plant would be the entire amp/motor package and feedback loop in the diagram at the top is designed to control the position of the motor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Motor Modeling =&lt;br /&gt;
&lt;br /&gt;
For our purposes, we have chosen to model the motor using the following equation, where &amp;lt;math&amp;gt;\tau&amp;lt;/math&amp;gt; is the output torque, &amp;lt;math&amp;gt;k_m&amp;lt;/math&amp;gt; is the motor constant, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; is the command current, &amp;lt;math&amp;gt;\mu_d&amp;lt;/math&amp;gt; is the dynamic friction coefficient, &amp;lt;math&amp;gt;mu_s&amp;lt;/math&amp;gt; is the static friction, &amp;lt;math&amp;gt;\omega&amp;lt;/math&amp;gt; is the speed of the motor, and the &amp;lt;math&amp;gt;sgn&amp;lt;/math&amp;gt; function returns the sign of its argument.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \tau = k_m i - \mu_d \omega - \mu_s sgn(\omega) \,&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be easily solved to find the necessary command current (and thus the analog or PWM input) needed to follow a reference trajectory, which would be the feedforward model of our system.&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
&lt;br /&gt;
To determine the values of the parameters in the above equation, you should run a series of tests at various input levels to make sure the parameters are constant at various speeds and accelerations of the motor.  To set up the experiment you will need a mount for the motor (a table-mount vice works well), an object of known inertia (ex. momentum wheel), and you will need to hook up the encoder on the motor to a device that can read it in (ex. decoding chip connected to a PIC).&lt;br /&gt;
&lt;br /&gt;
== Experiment ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:motor_model_wiring.png|200px|Wiring diagram for the motor modeling setup|right]]&lt;br /&gt;
For each run of the experiment, the motor is driven by three periods of a square wave current at a specified amplitude.  Multiple periods are used to allow transient behavior to die down and for filtering purposes, described in the following section.  During each run the position from the encoder is recorded and post-processing is used to find the velocity and acceleration associated with the trajectory.&lt;br /&gt;
&lt;br /&gt;
Code used to drive the motor during the experiment can be downloaded [[Media:motor_model_PIC_code.zip|here]].  This code is meant to be run on the [Introduction to the PIC32|PIC32 board].  The basic wiring diagram is to the right and the datasheet for the LS7083 decoder can be found [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html|here] and includes all the wiring diagrams necessary.&lt;br /&gt;
&lt;br /&gt;
To actually run the experiment, use the MATLAB code [[Media:motor_model_analysis_code.zip|here]].  The function dataCollection takes in the amplitude of your square wave current and outputs this to the amp.  It then collects the trajectory data and saves it to a .mat file (see file for details on directory and file name format).  Note that the COM port, Imax (maximum current set on the amp), and other variables must be changed in both the MATLAB code and the amp or PIC.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:filtering_example.png|200px|An example of filtering data|right]]&lt;br /&gt;
To find the velocity and acceleration of the motor during the experiment, the raw data from the encoder must be smoothed otherwise there are large spikes in the calculated derivatives due to signal noise, etc.  To smooth the data, a moving average is used (this is why we collected extra periods of data, so we can still apply the moving average to the end points).  The idea of a moving average is the filtered value at a specific time is the average of the unfiltered value and the nearest N values in each direction.  Choosing a low N leads to less smoothing but retains more of the original data.  I found that an N of 5 was good for my data set, but this will be different for each application depending on the amount of noise, etc.  The number of points to use in the filter is the second (and optional) argument to the MATLAB file fitParameters.  In this function, the raw data is first smoothed using the moving average, then finite differences are used to calculate the velocity.  This is then smoothed using the same moving average and finite differences are used again to find the acceleration.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fitting Parameters ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:model_example.png|200px|An example of motor model data|right]]&lt;br /&gt;
Now that you have the acceleration, you can easily find the torque because you know the inertia of the object being rotated.  Going back to the model, you now have the torque and velocity so you can solve for the three unknowns.  You can also choose to model the motor as having a different set of parameters for positive and negative torques, something I found to work better than a single set of parameters.&lt;br /&gt;
&lt;br /&gt;
In the figure to the right, an example of a motor model is shown, with trials run at 50 mA intervals from 150 to 400 mA.  The filtered data is plotted as the dots and the ideal model based on the calculated parameters are the solid lines, this type of plot can be generated from the function batchProcess.  In this plot, the effect of filtering is evident in the rounded edges near the transition points (crossing zero velocity and zero acceleration lines).  You can also see the motor is reaching its maximum speed at 200 mA.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Model_example.png&amp;diff=19029</id>
		<title>File:Model example.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Model_example.png&amp;diff=19029"/>
		<updated>2010-09-05T17:19:45Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Filtering_example.png&amp;diff=19028</id>
		<title>File:Filtering example.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Filtering_example.png&amp;diff=19028"/>
		<updated>2010-09-05T17:19:32Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor_model_wiring.png&amp;diff=19027</id>
		<title>File:Motor model wiring.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor_model_wiring.png&amp;diff=19027"/>
		<updated>2010-09-05T17:19:06Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor_model_analysis_code.zip&amp;diff=19026</id>
		<title>File:Motor model analysis code.zip</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor_model_analysis_code.zip&amp;diff=19026"/>
		<updated>2010-09-05T17:18:56Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor_model_PIC_code.zip&amp;diff=19025</id>
		<title>File:Motor model PIC code.zip</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor_model_PIC_code.zip&amp;diff=19025"/>
		<updated>2010-09-05T17:18:44Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19024</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19024"/>
		<updated>2010-09-05T17:18:28Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Motor Modeling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setting up the Junus Amplifier =&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.png|thumb|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, use the USB to RS-232 cable to connect the amp to your PC.  If this doesn&amp;#039;t work you will need to find and install the driver for the HL-340 USB to serial converter (there is a copy of the driver in the folder Philip&amp;#039;s Files\usb-serial-driver.zip on the desktop of the PC used for the QNX manipulation project).  You will also need to download and install [http://www.copleycontrols.com/Motion/Downloads/index.html CME2] (Copley Motion Explorer); note that Copley&amp;#039;s documentation for the amplifier and software can also be downloaded from the same page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:copley_basic_setup.png|thumb|Basic Setup Menu|right]]&lt;br /&gt;
Open the program and add the COM port used by the USB to serial cable to the list (the list can be changed later in the Tools -&amp;gt; Communication Wizard menu).  Next go to Amplifier -&amp;gt; Basic Setup.  Here you select from the different operational modes and input types.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating Modes ==&lt;br /&gt;
* Current - This is the most commonly used mode.  Here, the amplifier will create an output current proportional to some input signal to drive the attached actuator.  In this mode there is only one control loop running within the amplifier making it the preferred choice (the more control that can be done outside the amp, the less of a black box it is).&lt;br /&gt;
* Velocity - This mode takes the current control mode and adds another feedback loop around the current control loop so that the velocity of the motor is proportional to the input signal.  For the Junus amps, the motor speed is estimated from the back emf of the motor during use, making it less reliable than the current control mode.&lt;br /&gt;
&lt;br /&gt;
== Command Sources ==&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:junus_amp_pin_diagram.png|thumb|Junus Amp Input Pin Diagram|right]]&lt;br /&gt;
The pin diagram for the Junus amp is found to the right.&lt;br /&gt;
* Analog Command - In this mode, an analog input is connected to pins 2 and 9, with the analog reference voltage going to pin 9 and the signal going to pin 2.  The voltage range for the input is +/- 10V with the output being proportional to the voltage, i.e. 0V is 0A (or 0rpm) output, +10V is maximum positive current output, and -10V is maximum negative current output.&lt;br /&gt;
* PWM Command - In this mode the output is related to the duty cycle of the PWM signal in one of two ways.  To switch between these modes, click on the PWM command button in the block diagram.&lt;br /&gt;
** 50% mode - This mode uses a single input pin (pin 3).  Here a 50% duty cycle is the zero point (0A or 0rpm) with 0% being fully negative and 100% being fully positive.&lt;br /&gt;
** 100% mode - In addition to the PWM input pin there is an extra input pin (pin 4) to control the sign (or direction) of the output.  Here, a 0% duty cycle is the zero point, 100% duty cycle with the direction pin LO is fully negative and 100% duty cycle with the direction pin HI is fully positive.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now click on the Motor button in the block diagram.  Here you can input all the necessary parameters about your motor from the data sheet, or that you experimentally found.  Now you are ready to look at the control loop.  There is a PI controller with tunable parameters used to control the output current.  While you are welcome to play around with the parameters on your own, I would suggest that you click on the I Loop button and select Auto Tune, at least to get a starting point for the parameters.  It will give you several options based on different levels of aggressiveness of the controller.&lt;br /&gt;
&lt;br /&gt;
Click on Input/Output.  Here you can set up the different input and output pins.  I recommend using IN1 as Amp Enable-HI (or LO) Enables With Clear Faults (pin 13).  This ensures that the motor can only spin when you give it a command to turn on.  Choose HI if your digital outputs default to LO, or vice versa, as it can vary depending on the presence of pull-up resistors, etc.  You now have your amp configured and you are ready to start controlling your motor.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of other utilities built into the CME2 software.  The first is the Control Panel (second button from the left in the top menu).  This allows you to software enable/disable the amplifier as well as monitor various inputs/outputs of the motor during use.  The other is the Scope (third button from the left in the top menu).  This lets you apply various functions to drive the motor and monitor inputs/outputs over time.  This is useful for making sure your control parameters are tuned the way you like them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Using the Motor =&lt;br /&gt;
&lt;br /&gt;
If you are using analog command mode, a simple test to make sure your setup is working correctly is to connect the enable pin to +5V (or GND, depending on how it was configured) and use a potentiometer to control the input voltage and make sure the motor spins as you would expect it to.  As a reminder, 0V is 0 output, negative voltage will move it in one direction and positive voltage in the other.&lt;br /&gt;
&lt;br /&gt;
If you are using PWM command mode, a more involved test would be to do the activity found [[ME 333 Lab 4 | here]].  For our system, the plant would be the entire amp/motor package and feedback loop in the diagram at the top is designed to control the position of the motor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Motor Modeling =&lt;br /&gt;
&lt;br /&gt;
For our purposes, we have chosen to model the motor using the following equation, where &amp;lt;math&amp;gt;\tau&amp;lt;/math&amp;gt; is the output torque, &amp;lt;math&amp;gt;k_m&amp;lt;/math&amp;gt; is the motor constant, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; is the command current, &amp;lt;math&amp;gt;\mu_d&amp;lt;/math&amp;gt; is the dynamic friction coefficient, &amp;lt;math&amp;gt;mu_s&amp;lt;/math&amp;gt; is the static friction, &amp;lt;math&amp;gt;\omega&amp;lt;/math&amp;gt; is the speed of the motor, and the &amp;lt;math&amp;gt;sgn&amp;lt;/math&amp;gt; function returns the sign of its argument.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \tau = k_m i - \mu_d \omega - \mu_s sgn(\omega) \,&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be easily solved to find the necessary command current (and thus the analog or PWM input) needed to follow a reference trajectory, which would be the feedforward model of our system.&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
&lt;br /&gt;
To determine the values of the parameters in the above equation, you should run a series of tests at various input levels to make sure the parameters are constant at various speeds and accelerations of the motor.  To set up the experiment you will need a mount for the motor (a table-mount vice works well), an object of known inertia (ex. momentum wheel), and you will need to hook up the encoder on the motor to a device that can read it in (ex. decoding chip connected to a PIC).&lt;br /&gt;
&lt;br /&gt;
== Experiment ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:motor_model_wiring.png|200px|Wiring diagram for the motor modeling setup|right]]&lt;br /&gt;
For each run of the experiment, the motor is driven by three periods of a square wave current at a specified amplitude.  Multiple periods are used to allow transient behavior to die down and for filtering purposes, described in the following section.  During each run the position from the encoder is recorded and post-processing is used to find the velocity and acceleration associated with the trajectory.&lt;br /&gt;
&lt;br /&gt;
Code used to drive the motor during the experiment can be downloaded [[Media:motor_model_PIC_code.zip|here]].  This code is meant to be run on the [Introduction to the PIC32|PIC32 board].  The basic wiring diagram is to the right and the datasheet for the LS7083 decoder can be found [[http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html|here]] and includes all the wiring diagrams necessary.&lt;br /&gt;
&lt;br /&gt;
To actually run the experiment, use the MATLAB code [[Media:motor_model_analysis_code.zip|here]].  The function dataCollection takes in the amplitude of your square wave current and outputs this to the amp.  It then collects the trajectory data and saves it to a .mat file (see file for details on directory and file name format).  Note that the COM port, Imax (maximum current set on the amp), and other variables must be changed in both the MATLAB code and the amp or PIC.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:filtering_example.png|200px|An example of filtering data|right]]&lt;br /&gt;
To find the velocity and acceleration of the motor during the experiment, the raw data from the encoder must be smoothed otherwise there are large spikes in the calculated derivatives due to signal noise, etc.  To smooth the data, a moving average is used (this is why we collected extra periods of data, so we can still apply the moving average to the end points).  The idea of a moving average is the filtered value at a specific time is the average of the unfiltered value and the nearest N values in each direction.  Choosing a low N leads to less smoothing but retains more of the original data.  I found that an N of 5 was good for my data set, but this will be different for each application depending on the amount of noise, etc.  The number of points to use in the filter is the second (and optional) argument to the MATLAB file fitParameters.  In this function, the raw data is first smoothed using the moving average, then finite differences are used to calculate the velocity.  This is then smoothed using the same moving average and finite differences are used again to find the acceleration.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fitting Parameters ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:model_example.png|200px|An example of motor model data|right]]&lt;br /&gt;
Now that you have the acceleration, you can easily find the torque because you know the inertia of the object being rotated.  Going back to the model, you now have the torque and velocity so you can solve for the three unknowns.  You can also choose to model the motor as having a different set of parameters for positive and negative torques, something I found to work better than a single set of parameters.&lt;br /&gt;
&lt;br /&gt;
In the figure to the right, an example of a motor model is shown, with trials run at 50 mA intervals from 150 to 400 mA.  The filtered data is plotted as the dots and the ideal model based on the calculated parameters are the solid lines, this type of plot can be generated from the function batchProcess.  In this plot, the effect of filtering is evident in the rounded edges near the transition points (crossing zero velocity and zero acceleration lines).  You can also see the motor is reaching its maximum speed at 200 mA.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19023</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19023"/>
		<updated>2010-09-04T18:43:19Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setting up the Junus Amplifier =&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.png|thumb|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, use the USB to RS-232 cable to connect the amp to your PC.  If this doesn&amp;#039;t work you will need to find and install the driver for the HL-340 USB to serial converter (there is a copy of the driver in the folder Philip&amp;#039;s Files\usb-serial-driver.zip on the desktop of the PC used for the QNX manipulation project).  You will also need to download and install [http://www.copleycontrols.com/Motion/Downloads/index.html CME2] (Copley Motion Explorer); note that Copley&amp;#039;s documentation for the amplifier and software can also be downloaded from the same page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:copley_basic_setup.png|thumb|Basic Setup Menu|right]]&lt;br /&gt;
Open the program and add the COM port used by the USB to serial cable to the list (the list can be changed later in the Tools -&amp;gt; Communication Wizard menu).  Next go to Amplifier -&amp;gt; Basic Setup.  Here you select from the different operational modes and input types.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating Modes ==&lt;br /&gt;
* Current - This is the most commonly used mode.  Here, the amplifier will create an output current proportional to some input signal to drive the attached actuator.  In this mode there is only one control loop running within the amplifier making it the preferred choice (the more control that can be done outside the amp, the less of a black box it is).&lt;br /&gt;
* Velocity - This mode takes the current control mode and adds another feedback loop around the current control loop so that the velocity of the motor is proportional to the input signal.  For the Junus amps, the motor speed is estimated from the back emf of the motor during use, making it less reliable than the current control mode.&lt;br /&gt;
&lt;br /&gt;
== Command Sources ==&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:junus_amp_pin_diagram.png|thumb|Junus Amp Input Pin Diagram|right]]&lt;br /&gt;
The pin diagram for the Junus amp is found to the right.&lt;br /&gt;
* Analog Command - In this mode, an analog input is connected to pins 2 and 9, with the analog reference voltage going to pin 9 and the signal going to pin 2.  The voltage range for the input is +/- 10V with the output being proportional to the voltage, i.e. 0V is 0A (or 0rpm) output, +10V is maximum positive current output, and -10V is maximum negative current output.&lt;br /&gt;
* PWM Command - In this mode the output is related to the duty cycle of the PWM signal in one of two ways.  To switch between these modes, click on the PWM command button in the block diagram.&lt;br /&gt;
** 50% mode - This mode uses a single input pin (pin 3).  Here a 50% duty cycle is the zero point (0A or 0rpm) with 0% being fully negative and 100% being fully positive.&lt;br /&gt;
** 100% mode - In addition to the PWM input pin there is an extra input pin (pin 4) to control the sign (or direction) of the output.  Here, a 0% duty cycle is the zero point, 100% duty cycle with the direction pin LO is fully negative and 100% duty cycle with the direction pin HI is fully positive.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now click on the Motor button in the block diagram.  Here you can input all the necessary parameters about your motor from the data sheet, or that you experimentally found.  Now you are ready to look at the control loop.  There is a PI controller with tunable parameters used to control the output current.  While you are welcome to play around with the parameters on your own, I would suggest that you click on the I Loop button and select Auto Tune, at least to get a starting point for the parameters.  It will give you several options based on different levels of aggressiveness of the controller.&lt;br /&gt;
&lt;br /&gt;
Click on Input/Output.  Here you can set up the different input and output pins.  I recommend using IN1 as Amp Enable-HI (or LO) Enables With Clear Faults (pin 13).  This ensures that the motor can only spin when you give it a command to turn on.  Choose HI if your digital outputs default to LO, or vice versa, as it can vary depending on the presence of pull-up resistors, etc.  You now have your amp configured and you are ready to start controlling your motor.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of other utilities built into the CME2 software.  The first is the Control Panel (second button from the left in the top menu).  This allows you to software enable/disable the amplifier as well as monitor various inputs/outputs of the motor during use.  The other is the Scope (third button from the left in the top menu).  This lets you apply various functions to drive the motor and monitor inputs/outputs over time.  This is useful for making sure your control parameters are tuned the way you like them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Using the Motor =&lt;br /&gt;
&lt;br /&gt;
If you are using analog command mode, a simple test to make sure your setup is working correctly is to connect the enable pin to +5V (or GND, depending on how it was configured) and use a potentiometer to control the input voltage and make sure the motor spins as you would expect it to.  As a reminder, 0V is 0 output, negative voltage will move it in one direction and positive voltage in the other.&lt;br /&gt;
&lt;br /&gt;
If you are using PWM command mode, a more involved test would be to do the activity found [[ME 333 Lab 4 | here]].  For our system, the plant would be the entire amp/motor package and feedback loop in the diagram at the top is designed to control the position of the motor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Motor Modeling =&lt;br /&gt;
&lt;br /&gt;
For our purposes, we have chosen to model the motor using the following equation, where &amp;lt;math&amp;gt;\tau&amp;lt;/math&amp;gt; is the output torque, &amp;lt;math&amp;gt;k_m&amp;lt;/math&amp;gt; is the motor constant, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; is the command current, &amp;lt;math&amp;gt;\mu_d&amp;lt;/math&amp;gt; is the dynamic friction coefficient, &amp;lt;math&amp;gt;mu_s&amp;lt;/math&amp;gt; is the static friction, &amp;lt;math&amp;gt;\omega&amp;lt;/math&amp;gt; is the speed of the motor, and the &amp;lt;math&amp;gt;sgn&amp;lt;/math&amp;gt; function returns the sign of its argument.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \tau = k_m i - \mu_d \omega - \mu_s sgn(\omega) \,&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be easily solved to find the necessary command current (and thus the analog or PWM input) needed to follow a reference trajectory, which would be the feedforward model of our system.&lt;br /&gt;
&lt;br /&gt;
To determine the values of the parameters in the above equation, you must run a series of tests at various input levels (at least 3, but more are recommended to make sure the parameters are constant at various speeds and accelerations of the motor).  To set up the experiment you will need a mount for the motor (a table-mount vice works well), an object of known inertia (ex. momentum wheel), and you will need to hook up the encoder on the motor to a device that can read it in.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Junus_amp_pin_diagram.png&amp;diff=19022</id>
		<title>File:Junus amp pin diagram.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Junus_amp_pin_diagram.png&amp;diff=19022"/>
		<updated>2010-09-04T17:42:41Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Copley_basic_setup.png&amp;diff=19021</id>
		<title>File:Copley basic setup.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Copley_basic_setup.png&amp;diff=19021"/>
		<updated>2010-09-04T17:42:32Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19020</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19020"/>
		<updated>2010-09-04T17:42:19Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setting up the Junus Amplifier =&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.png|thumb|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, use the USB to RS-232 cable to connect the amp to your PC.  If this doesn&amp;#039;t work you will need to find and install the driver for the HL-340 USB to serial converter (there is a copy of the driver in the folder Philip&amp;#039;s Files\usb-serial-driver.zip on the desktop of the PC used for the QNX manipulation project).  You will also need to download and install [http://www.copleycontrols.com/Motion/Downloads/index.html CME2] (Copley Motion Explorer); note that Copley&amp;#039;s documentation for the amplifier and software can also be downloaded from the same page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:copley_basic_setup.png|thumb|Basic Setup Menu|right]]&lt;br /&gt;
Open the program and add the COM port used by the USB to serial cable to the list (the list can be changed later in the Tools -&amp;gt; Communication Wizard menu).  Next go to Amplifier -&amp;gt; Basic Setup.  Here you select from the different operational modes and input types.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating Modes ==&lt;br /&gt;
* Current - This is the most commonly used mode.  Here, the amplifier will create an output current proportional to some input signal to drive the attached actuator.  In this mode there is only one control loop running within the amplifier making it the preferred choice (the more control that can be done outside the amp, the less of a black box it is).&lt;br /&gt;
* Velocity - This mode takes the current control mode and adds another feedback loop around the current control loop so that the velocity of the motor is proportional to the input signal.  For the Junus amps, the motor speed is estimated from the back emf of the motor during use, making it less reliable than the current control mode.&lt;br /&gt;
&lt;br /&gt;
== Command Sources ==&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:junus_amp_pin_diagram.png|thumb|Junus Amp Input Pin Diagram|right]]&lt;br /&gt;
The pin diagram for the Junus amp is found to the right.&lt;br /&gt;
* Analog Command - In this mode, an analog input is connected to pins 2 and 9, with the analog reference voltage going to pin 9 and the signal going to pin 2.  The voltage range for the input is +/- 10V with the output being proportional to the voltage, i.e. 0V is 0A (or 0rpm) output, +10V is maximum positive current output, and -10V is maximum negative current output.&lt;br /&gt;
* PWM Command - In this mode the output is related to the duty cycle of the PWM signal in one of two ways.  To switch between these modes, click on the PWM command button in the block diagram.&lt;br /&gt;
** 50% mode - This mode uses a single input pin (pin 3).  Here a 50% duty cycle is the zero point (0A or 0rpm) with 0% being fully negative and 100% being fully positive.&lt;br /&gt;
** 100% mode - In addition to the PWM input pin there is an extra input pin (pin 4) to control the sign (or direction) of the output.  Here, a 0% duty cycle is the zero point, 100% duty cycle with the direction pin LO is fully negative and 100% duty cycle with the direction pin HI is fully positive.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19019</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19019"/>
		<updated>2010-09-04T16:58:11Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setting up the Junus Amplifier =&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.png|thumb|150px|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Power_supply_diagram.png&amp;diff=19018</id>
		<title>File:Power supply diagram.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Power_supply_diagram.png&amp;diff=19018"/>
		<updated>2010-09-04T16:57:38Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: uploaded a new version of &amp;quot;Image:Power supply diagram.png&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19017</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19017"/>
		<updated>2010-09-04T16:57:29Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setting up the Junus Amplifier =&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.JPG|thumb|150px|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19016</id>
		<title>Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Setup,_Use,_and_Modeling_of_Harmonic_Drive_Motors_with_Junus_Amps&amp;diff=19016"/>
		<updated>2010-09-04T16:56:36Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: New page: * Setting up the Junus Amplifier  right The first thing you need to run the amplifier is to find a DC power source that ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Setting up the Junus Amplifier&lt;br /&gt;
&lt;br /&gt;
[[Image:power_supply_diagram.JPG|thumb|150px|Power Supply Diagram|right]]&lt;br /&gt;
The first thing you need to run the amplifier is to find a DC power source that outputs 20-90V with a maximum current greater than what you expect your motor(s) to draw.  This should be connected to the amplifier according to the following diagram, where the capacitors and diodes are rated for the voltages/currents you are expecting to see.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Power_supply_diagram.png&amp;diff=19015</id>
		<title>File:Power supply diagram.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Power_supply_diagram.png&amp;diff=19015"/>
		<updated>2010-09-04T16:56:09Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Projects_and_miscellaneous&amp;diff=19014</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=19014"/>
		<updated>2010-09-04T16:49:08Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[ME 333 final projects]]&lt;br /&gt;
*[[Real-Time Linux for TrackCam]]&lt;br /&gt;
*[[NI-DAQ Cards on Linux]]&lt;br /&gt;
*[[PPOD Experiments with a Textured Plate]]&lt;br /&gt;
*[[VPOD 3DOF Vibratory Device]]&lt;br /&gt;
*[[Design and Control of a Pantograph Robot]]&lt;br /&gt;
*[[PIC Motor Control with EEPROM and Interactive Menu Example]]&lt;br /&gt;
*[[Swarm Robot Project Overview]]&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;
*[[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;
*[[PIC USB]]&lt;br /&gt;
*[[MATLAB Motor Controller]]&lt;br /&gt;
*[[Flexure Characterization and Design]]&lt;br /&gt;
*[[Bouncing Polygon Simulator]]&lt;br /&gt;
*[[Control with TrackCam Vision Feedback and MATLAB]]&lt;br /&gt;
*[[High Speed Vision System and Object Tracking]]&lt;br /&gt;
*[[MonkeyBot Simulation Project]]&lt;br /&gt;
*[[PPOD-mini Project]]&lt;br /&gt;
*[[PPOD User Guide]]&lt;br /&gt;
*[[PIC32MX: High-speed Wireless Communication]]&lt;br /&gt;
*[[Setup, Use, and Modeling of Harmonic Drive Motors with Junus Amps]]&lt;br /&gt;
*[[test]]&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Projects_and_miscellaneous&amp;diff=19013</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=19013"/>
		<updated>2010-09-04T16:45:40Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[ME 333 final projects]]&lt;br /&gt;
*[[Real-Time Linux for TrackCam]]&lt;br /&gt;
*[[NI-DAQ Cards on Linux]]&lt;br /&gt;
*[[PPOD Experiments with a Textured Plate]]&lt;br /&gt;
*[[VPOD 3DOF Vibratory Device]]&lt;br /&gt;
*[[Design and Control of a Pantograph Robot]]&lt;br /&gt;
*[[PIC Motor Control with EEPROM and Interactive Menu Example]]&lt;br /&gt;
*[[Swarm Robot Project Overview]]&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;
*[[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;
*[[PIC USB]]&lt;br /&gt;
*[[MATLAB Motor Controller]]&lt;br /&gt;
*[[Flexure Characterization and Design]]&lt;br /&gt;
*[[Bouncing Polygon Simulator]]&lt;br /&gt;
*[[Control with TrackCam Vision Feedback and MATLAB]]&lt;br /&gt;
*[[High Speed Vision System and Object Tracking]]&lt;br /&gt;
*[[MonkeyBot Simulation Project]]&lt;br /&gt;
*[[PPOD-mini Project]]&lt;br /&gt;
*[[PPOD User Guide]]&lt;br /&gt;
*[[PIC32MX: High-speed Wireless Communication]]&lt;br /&gt;
*[[Setup, Use, and Modeling of Harmonic Drive Motors]]&lt;br /&gt;
*[[test]]&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=18139</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=18139"/>
		<updated>2010-03-19T08:06:13Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
Watch [http://www.youtube.com/watch?v=7j37NCYWHF8 Haptikos] (and the other projects) in action on YouTube.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf thesis] work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible. The backboard of the pantograph is screwed into the bottom. The motors were held in place by a set of holes in the top plate and a second bracket suspended between the top and bottom. Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using two [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control instead of speed control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Michael Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page for the TR-36, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC and read in on the timer pins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RS-232 Communication with PC ===&lt;br /&gt;
&lt;br /&gt;
We found that reliable communication between the different components of our system was one of the more challenging aspects of the project.  Because of this, we decided to post our code here as a quick reference instead of downloading the code from above.  The desired baud rates for serial (DESIRED_BAUDRATE) and I2C (BRG_VAL) communication were defined at the beginning of the code to be&lt;br /&gt;
&lt;br /&gt;
 #define DESIRED_BAUDRATE       19200      // The desired BaudRate RS-232&lt;br /&gt;
 #define Fsck   		50000      // Frequency&lt;br /&gt;
 #define BRG_VAL    		((SYS_FREQ/2/Fsck)-2)   // Baud rate generator value&lt;br /&gt;
&lt;br /&gt;
This first function initializes the UART1 port on the PIC.  For an more detailed explanation of the configuration variables, and other UART functions, see chapter 16 of the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]].&lt;br /&gt;
&lt;br /&gt;
 void initUART1(int pbClk)&lt;br /&gt;
 {&lt;br /&gt;
     // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
     // Module Enable &lt;br /&gt;
     // Work in IDLE mode &lt;br /&gt;
     // Communication through usual pins &lt;br /&gt;
     // Disable wake-up &lt;br /&gt;
     // Loop back disabled &lt;br /&gt;
     // Input to Capture module from ICx pin &lt;br /&gt;
     // no parity 8 bit &lt;br /&gt;
     // 1 stop bit &lt;br /&gt;
     // IRDA encoder and decoder disabled &lt;br /&gt;
     // CTS and RTS pins are disabled &lt;br /&gt;
     // UxRX idle state is &amp;#039;1&amp;#039; &lt;br /&gt;
     // 16x baud clock - normal speed&lt;br /&gt;
     #define config1    UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
    &lt;br /&gt;
     // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
     // IrDA encoded UxTX idle state is &amp;#039;0&amp;#039;&lt;br /&gt;
     // Enable UxRX pin&lt;br /&gt;
     // Enable UxTX pin&lt;br /&gt;
     // Interrupt on transfer of every character to TSR &lt;br /&gt;
     // Interrupt on every char received&lt;br /&gt;
     // Disable 9-bit address detect&lt;br /&gt;
     // Rx Buffer Over run status bit clear&lt;br /&gt;
     #define config2      UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR   &lt;br /&gt;
  &lt;br /&gt;
     // Open UART2 with config1 and config2&lt;br /&gt;
     OpenUART1( config1, config2, SYS_FREQ/16/DESIRED_BAUDRATE-1);   // calculate actual BAUD generate value.&lt;br /&gt;
        &lt;br /&gt;
     // Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
     ConfigIntUART1(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next initialization function configures Timer1 which is used to generate an interrupt every 10 ms that sends location data to the PC.  The timer is configured to add one count every 64 clock cycles of the PIC with a priority of 7 (the highest value) as the feedback to the computer is important for rendering the game correctly.  Because this is higher priority, it may be necessary to increase the period of the interrupt if the PIC is receiving longer packets of information from the PC.  This function also initializes the I2C communication ports (further explanation of this below).&lt;br /&gt;
&lt;br /&gt;
 void initInterruptComm()&lt;br /&gt;
 {&lt;br /&gt;
    // Initialize timer 1 to generate interrupt to send data to PC&lt;br /&gt;
    // init Timer1 mode and period (PR1) // produces 10ms period&lt;br /&gt;
    OpenTimer1( T1_ON | T1_PS_1_64 | T1_SOURCE_INT, 12499); &lt;br /&gt;
      &lt;br /&gt;
    mT1SetIntPriority(7);    // set Timer1 Interrupt Priority&lt;br /&gt;
    mT1ClearIntFlag();       // clear interrupt flag&lt;br /&gt;
    mT1IntEnable(1);         // enable timer1 interrupts&lt;br /&gt;
 &lt;br /&gt;
    // Initialize I2C lines to communicate data to DACs&lt;br /&gt;
    OpenI2C1( I2C_EN, BRG_VAL );&lt;br /&gt;
    OpenI2C2( I2C_EN, BRG_VAL );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then we create an interrupt handler for UART1 which is triggered when the PIC detects that there is data in the serial buffer.  This is set to a priority level of 2 because it is less important than sending location information to the PC.  The function ReadUART1 retrieves a single character from the serial buffer; use getsUART1() for strings.&lt;br /&gt;
&lt;br /&gt;
 // UART 1 interrupt handler&lt;br /&gt;
 // it is set at priority level 2&lt;br /&gt;
 void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned char force;&lt;br /&gt;
 &lt;br /&gt;
    // Is this an RX interrupt?&lt;br /&gt;
    if(mU1RXGetIntFlag()) {&lt;br /&gt;
         // Clear the RX interrupt Flag&lt;br /&gt;
         mU1RXClearIntFlag();&lt;br /&gt;
    &lt;br /&gt;
         force = ReadUART1(); // get data from PC&lt;br /&gt;
         mLED_0_Toggle(); // toggle LED for feedback&lt;br /&gt;
         MAX518(force); // send signal to motors&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // We don&amp;#039;t care about TX interrupt&lt;br /&gt;
    if ( mU1TXGetIntFlag() ) {&lt;br /&gt;
         mU1TXClearIntFlag();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We also create an interrupt controller for Timer1 to send position information back at the pre-defined rate of 10ms.  The function uses putsUART1 which sends a string of data to the PC, which then parses the string into the individual components.  The end line character &amp;quot;\n&amp;quot; is useful so the PC knows that it has received the entire data string, though any character could be used.&lt;br /&gt;
&lt;br /&gt;
 // interrput code for the timer 1&lt;br /&gt;
 void __ISR( _TIMER_1_VECTOR, ipl7) T1Interrupt( void)&lt;br /&gt;
 {&lt;br /&gt;
     // send data to PC every 10 ms (based on Timer1)&lt;br /&gt;
     char RS232_Out_Buffer[32];&lt;br /&gt;
     sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d\n&amp;quot;,X, Y, phi1, phi2);&lt;br /&gt;
     putsUART1(RS232_Out_Buffer);&lt;br /&gt;
 &lt;br /&gt;
     mLED_3_Toggle(); // toggle LED for feedback&lt;br /&gt;
     &lt;br /&gt;
     // clear interrupt flag and exit&lt;br /&gt;
     mT1ClearIntFlag();&lt;br /&gt;
 } // T1 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I2C Communication with DACs ===&lt;br /&gt;
&lt;br /&gt;
The two I2C ports were initialized above in the initInterruptComm() function.  The I2C communication also uses functions from the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]], found in chapter 15.  The general structure of the function is to send a series of commands to the DAC and wait for this to complete after each command.  First, the Start command is sent, then Idle waits until the I2C line is no longer busy.  Then the address of the chip on the I2C line is sent out and the PIC waits until the chip has acknowledged (ACK-ed).  This address is defined by the chips used as well as the configuration pins set when wiring the chips.  It then sends the command byte to tell the DAC to get ready to output data and finally it sends the data byte telling the DAC the voltage level to output.  The I2C line is then closed to avoid sending extraneous data and the process is repeated for the second DAC.  This information will change depending on the device being interfaced with (particularly if the PIC has to switch from master to slave mode) but the basic principles outlined here can be used for most applications.&lt;br /&gt;
&lt;br /&gt;
 void MAX518(int force)&lt;br /&gt;
 {&lt;br /&gt;
     unsigned char addr = 0b01011000; // address of DAC on I2C line&lt;br /&gt;
     unsigned char cmd = 0x00; //command line &lt;br /&gt;
     int force1 = 127+(7-(force &amp;gt;&amp;gt; 4))*8; // upper nibble to motor 1&lt;br /&gt;
     int force2 = 127+(7-(force &amp;amp; 15))*8; // lower nibble to motor 2&lt;br /&gt;
    &lt;br /&gt;
     // Send to DAC 1 //////////////////////&lt;br /&gt;
     StartI2C1();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C1();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (addr); //address &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (cmd); //command line &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1(force1); //output &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C1();  //end of data send &lt;br /&gt;
     IdleI2C1();  //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     // Send to DAC 2 //////////////////////&lt;br /&gt;
     StartI2C2();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C2();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2 (addr); //address &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
       &lt;br /&gt;
     MasterWriteI2C2 (cmd); //command line &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2(force2); //output &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C2();  //end of data send &lt;br /&gt;
     IdleI2C2();  //Wait to complete &lt;br /&gt;
 }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in [[Processing]], a Java-based programming language that makes the creation of graphics very easy.  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
* Common ground - When connecting several circuit boards together, make sure they have a common ground.  If this is not done, the ground from one board can float relative to the other boards and cause problems when sending signals between boards.&lt;br /&gt;
* Current limitations - When using DC/DC converters, exceeding the maximum current may cause the converter voltage output to decrease.&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Impedance_matching Impedance matching] - As with all modular circuitry, make sure that the output impedance of one circuit is matched to the input of the connected circuit.&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=18128</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=18128"/>
		<updated>2010-03-19T07:48:28Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Game Programming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
Watch [http://www.youtube.com/watch?v=7j37NCYWHF8 Haptikos] (and the other projects) in action on YouTube.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible. The backboard of the pantograph is screwed into the bottom. The motors were held in place by a set of holes in the top plate and a second bracket suspended between the top and bottom. Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page for the TR-36, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC and read in on the timer pins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RS-232 Communication with PC ===&lt;br /&gt;
&lt;br /&gt;
We found that reliable communication between the different components of our system was one of the more challenging aspects of the project.  Because of this, we decided to post our code here as a quick reference.  The desired baud rates for serial (DESIRED_BAUDRATE) and I2C (BRG_VAL) communication were defined at the beginning of the code to be&lt;br /&gt;
&lt;br /&gt;
 #define DESIRED_BAUDRATE       19200      // The desired BaudRate RS-232&lt;br /&gt;
 #define Fsck   					50000 &lt;br /&gt;
 #define BRG_VAL    				((SYS_FREQ/2/Fsck)-2) &lt;br /&gt;
&lt;br /&gt;
This first function initializes the UART1 port on the PIC.  For an explanation of the configuration variables, and other UART functions, see chapter 16 of the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]].&lt;br /&gt;
&lt;br /&gt;
 void initUART1(int pbClk)&lt;br /&gt;
 {&lt;br /&gt;
     // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
     // Module Enable &lt;br /&gt;
     // Work in IDLE mode &lt;br /&gt;
     // Communication through usual pins &lt;br /&gt;
     // Disable wake-up &lt;br /&gt;
     // Loop back disabled &lt;br /&gt;
     // Input to Capture module from ICx pin &lt;br /&gt;
     // no parity 8 bit &lt;br /&gt;
     // 1 stop bit &lt;br /&gt;
     // IRDA encoder and decoder disabled &lt;br /&gt;
     // CTS and RTS pins are disabled &lt;br /&gt;
     // UxRX idle state is &amp;#039;1&amp;#039; &lt;br /&gt;
     // 16x baud clock - normal speed&lt;br /&gt;
     #define config1    UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
    &lt;br /&gt;
     // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
     // IrDA encoded UxTX idle state is &amp;#039;0&amp;#039;&lt;br /&gt;
     // Enable UxRX pin&lt;br /&gt;
     // Enable UxTX pin&lt;br /&gt;
     // Interrupt on transfer of every character to TSR &lt;br /&gt;
     // Interrupt on every char received&lt;br /&gt;
     // Disable 9-bit address detect&lt;br /&gt;
     // Rx Buffer Over run status bit clear&lt;br /&gt;
     #define config2      UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR   &lt;br /&gt;
  &lt;br /&gt;
     // Open UART2 with config1 and config2&lt;br /&gt;
     OpenUART1( config1, config2, SYS_FREQ/16/DESIRED_BAUDRATE-1);   // calculate actual BAUD generate value.&lt;br /&gt;
        &lt;br /&gt;
     // Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
     ConfigIntUART1(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next initialization function configures Timer1 which is used to generate an interrupt every 10 ms that sends location data to the PC.  The timer is configured to add one count every 64 clock cycles of the PIC with a priority of 7 (the highest value) as the feedback to the computer is important for rendering the game correctly.&lt;br /&gt;
&lt;br /&gt;
 void initInterruptComm()&lt;br /&gt;
 {&lt;br /&gt;
    // Initialize timer 1 to generate interrupt to send data to PC&lt;br /&gt;
    // init Timer1 mode and period (PR1) // produces 10ms period&lt;br /&gt;
    OpenTimer1( T1_ON | T1_PS_1_64 | T1_SOURCE_INT, 12499); &lt;br /&gt;
      &lt;br /&gt;
    mT1SetIntPriority(7);    // set Timer1 Interrupt Priority&lt;br /&gt;
    mT1ClearIntFlag();       // clear interrupt flag&lt;br /&gt;
    mT1IntEnable(1);         // enable timer1 interrupts&lt;br /&gt;
 &lt;br /&gt;
    // Initialize I2C lines to communicate data to DACs&lt;br /&gt;
    OpenI2C1( I2C_EN, BRG_VAL );&lt;br /&gt;
    OpenI2C2( I2C_EN, BRG_VAL );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then we create an interrupt handler for UART1 which is triggered when the PIC detects that there is data in the serial buffer.  This is set to a priority level of 2 because it is less important than sending location information to the PC.  The function ReadUART1 retrieves a single character from the serial buffer, use getsUART1() for strings.&lt;br /&gt;
&lt;br /&gt;
 // UART 1 interrupt handler&lt;br /&gt;
 // it is set at priority level 2&lt;br /&gt;
 void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned char force;&lt;br /&gt;
 &lt;br /&gt;
    // Is this an RX interrupt?&lt;br /&gt;
    if(mU1RXGetIntFlag()) {&lt;br /&gt;
         // Clear the RX interrupt Flag&lt;br /&gt;
         mU1RXClearIntFlag();&lt;br /&gt;
    &lt;br /&gt;
         force = ReadUART1(); // get data from PC&lt;br /&gt;
         mLED_0_Toggle(); // toggle LED for feedback&lt;br /&gt;
         MAX518(force); // send signal to motors&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // We don&amp;#039;t care about TX interrupt&lt;br /&gt;
    if ( mU1TXGetIntFlag() ) {&lt;br /&gt;
         mU1TXClearIntFlag();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We also create an interrupt controller for Timer1 to send location information back at a pre-defined rate.  The function uses putsUART1 which sends a string of data.&lt;br /&gt;
&lt;br /&gt;
 // interrput code for the timer 1&lt;br /&gt;
 void __ISR( _TIMER_1_VECTOR, ipl7) T1Interrupt( void)&lt;br /&gt;
 {&lt;br /&gt;
     // send data to PC every 10 ms (based on Timer1)&lt;br /&gt;
     char RS232_Out_Buffer[32];&lt;br /&gt;
     sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d\n&amp;quot;,X, Y, phi1, phi2);&lt;br /&gt;
     putsUART1(RS232_Out_Buffer);&lt;br /&gt;
 &lt;br /&gt;
     mLED_3_Toggle(); // toggle LED for feedback&lt;br /&gt;
     &lt;br /&gt;
     // clear interrupt flag and exit&lt;br /&gt;
     mT1ClearIntFlag();&lt;br /&gt;
 } // T1 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I2C Communication with DACs ===&lt;br /&gt;
&lt;br /&gt;
The two I2C ports were initialized above in the initInterruptComm() function.  The I2C communication also uses functions from the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]], found in chapter 15.  The general structure of the function is to send a series of commands to the DAC and wait for this to complete after each command.  First, the Start command is sent, then Idle waits until the I2C line is no longer busy.  Then the address of the chip on the I2C line is sent out and the PIC waits until the chip has acknowledged (ACKed).  This addressed is defined by the chips used as well as the configuration pins set when wiring the device up.  It then sends the command byte to tell the DAC to get ready to output data and finally it sends the data byte telling the DAC how much voltage to output.  The line is then closed to avoid sending extraneous data and the process is repeated for the second DAC.  This information will change depending on the device being interfaced with (particularly if the PIC has to switch from master to slave mode) but the basic principles outlined here can be used for most applications.&lt;br /&gt;
&lt;br /&gt;
 void MAX518(int force)&lt;br /&gt;
 {&lt;br /&gt;
     unsigned char addr = 0b01011000; // address of DAC on I2C line&lt;br /&gt;
     unsigned char cmd = 0x00; //command line &lt;br /&gt;
     int force1 = 127+(7-(force &amp;gt;&amp;gt; 4))*8; // upper nibble to motor 1&lt;br /&gt;
     int force2 = 127+(7-(force &amp;amp; 15))*8; // lower nibble to motor 2&lt;br /&gt;
    &lt;br /&gt;
     // Send to DAC 1 //////////////////////&lt;br /&gt;
     StartI2C1();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C1();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (addr); //address &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (cmd); //command line &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1(force1); //output &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C1();  //end of data send &lt;br /&gt;
     IdleI2C1();  //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     // Send to DAC 2 //////////////////////&lt;br /&gt;
     StartI2C2();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C2();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2 (addr); //address &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
       &lt;br /&gt;
     MasterWriteI2C2 (cmd); //command line &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2(force2); //output &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C2();  //end of data send &lt;br /&gt;
     IdleI2C2();  //Wait to complete &lt;br /&gt;
 }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in [[Processing]], a Java-based programming language.  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
* Common ground - When connecting several circuit boards together, make sure they have a common ground.  If this is not done, the ground from one board can float relative to the other boards and cause problems when sending signals between boards.&lt;br /&gt;
* Current limitations - When using DC/DC converters, exceeding the maximum current may cause the converter voltage output to decrease.&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Impedance_matching Impedance matching] - As with all modular circuitry, make sure that the output impedance of one circuit is matched to the input of the connected circuit.&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=18127</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=18127"/>
		<updated>2010-03-19T07:47:37Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Debugging Tips */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
Watch [http://www.youtube.com/watch?v=7j37NCYWHF8 Haptikos] (and the other projects) in action on YouTube.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible. The backboard of the pantograph is screwed into the bottom. The motors were held in place by a set of holes in the top plate and a second bracket suspended between the top and bottom. Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page for the TR-36, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC and read in on the timer pins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RS-232 Communication with PC ===&lt;br /&gt;
&lt;br /&gt;
We found that reliable communication between the different components of our system was one of the more challenging aspects of the project.  Because of this, we decided to post our code here as a quick reference.  The desired baud rates for serial (DESIRED_BAUDRATE) and I2C (BRG_VAL) communication were defined at the beginning of the code to be&lt;br /&gt;
&lt;br /&gt;
 #define DESIRED_BAUDRATE       19200      // The desired BaudRate RS-232&lt;br /&gt;
 #define Fsck   					50000 &lt;br /&gt;
 #define BRG_VAL    				((SYS_FREQ/2/Fsck)-2) &lt;br /&gt;
&lt;br /&gt;
This first function initializes the UART1 port on the PIC.  For an explanation of the configuration variables, and other UART functions, see chapter 16 of the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]].&lt;br /&gt;
&lt;br /&gt;
 void initUART1(int pbClk)&lt;br /&gt;
 {&lt;br /&gt;
     // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
     // Module Enable &lt;br /&gt;
     // Work in IDLE mode &lt;br /&gt;
     // Communication through usual pins &lt;br /&gt;
     // Disable wake-up &lt;br /&gt;
     // Loop back disabled &lt;br /&gt;
     // Input to Capture module from ICx pin &lt;br /&gt;
     // no parity 8 bit &lt;br /&gt;
     // 1 stop bit &lt;br /&gt;
     // IRDA encoder and decoder disabled &lt;br /&gt;
     // CTS and RTS pins are disabled &lt;br /&gt;
     // UxRX idle state is &amp;#039;1&amp;#039; &lt;br /&gt;
     // 16x baud clock - normal speed&lt;br /&gt;
     #define config1    UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
    &lt;br /&gt;
     // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
     // IrDA encoded UxTX idle state is &amp;#039;0&amp;#039;&lt;br /&gt;
     // Enable UxRX pin&lt;br /&gt;
     // Enable UxTX pin&lt;br /&gt;
     // Interrupt on transfer of every character to TSR &lt;br /&gt;
     // Interrupt on every char received&lt;br /&gt;
     // Disable 9-bit address detect&lt;br /&gt;
     // Rx Buffer Over run status bit clear&lt;br /&gt;
     #define config2      UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR   &lt;br /&gt;
  &lt;br /&gt;
     // Open UART2 with config1 and config2&lt;br /&gt;
     OpenUART1( config1, config2, SYS_FREQ/16/DESIRED_BAUDRATE-1);   // calculate actual BAUD generate value.&lt;br /&gt;
        &lt;br /&gt;
     // Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
     ConfigIntUART1(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next initialization function configures Timer1 which is used to generate an interrupt every 10 ms that sends location data to the PC.  The timer is configured to add one count every 64 clock cycles of the PIC with a priority of 7 (the highest value) as the feedback to the computer is important for rendering the game correctly.&lt;br /&gt;
&lt;br /&gt;
 void initInterruptComm()&lt;br /&gt;
 {&lt;br /&gt;
    // Initialize timer 1 to generate interrupt to send data to PC&lt;br /&gt;
    // init Timer1 mode and period (PR1) // produces 10ms period&lt;br /&gt;
    OpenTimer1( T1_ON | T1_PS_1_64 | T1_SOURCE_INT, 12499); &lt;br /&gt;
      &lt;br /&gt;
    mT1SetIntPriority(7);    // set Timer1 Interrupt Priority&lt;br /&gt;
    mT1ClearIntFlag();       // clear interrupt flag&lt;br /&gt;
    mT1IntEnable(1);         // enable timer1 interrupts&lt;br /&gt;
 &lt;br /&gt;
    // Initialize I2C lines to communicate data to DACs&lt;br /&gt;
    OpenI2C1( I2C_EN, BRG_VAL );&lt;br /&gt;
    OpenI2C2( I2C_EN, BRG_VAL );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then we create an interrupt handler for UART1 which is triggered when the PIC detects that there is data in the serial buffer.  This is set to a priority level of 2 because it is less important than sending location information to the PC.  The function ReadUART1 retrieves a single character from the serial buffer, use getsUART1() for strings.&lt;br /&gt;
&lt;br /&gt;
 // UART 1 interrupt handler&lt;br /&gt;
 // it is set at priority level 2&lt;br /&gt;
 void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned char force;&lt;br /&gt;
 &lt;br /&gt;
    // Is this an RX interrupt?&lt;br /&gt;
    if(mU1RXGetIntFlag()) {&lt;br /&gt;
         // Clear the RX interrupt Flag&lt;br /&gt;
         mU1RXClearIntFlag();&lt;br /&gt;
    &lt;br /&gt;
         force = ReadUART1(); // get data from PC&lt;br /&gt;
         mLED_0_Toggle(); // toggle LED for feedback&lt;br /&gt;
         MAX518(force); // send signal to motors&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // We don&amp;#039;t care about TX interrupt&lt;br /&gt;
    if ( mU1TXGetIntFlag() ) {&lt;br /&gt;
         mU1TXClearIntFlag();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We also create an interrupt controller for Timer1 to send location information back at a pre-defined rate.  The function uses putsUART1 which sends a string of data.&lt;br /&gt;
&lt;br /&gt;
 // interrput code for the timer 1&lt;br /&gt;
 void __ISR( _TIMER_1_VECTOR, ipl7) T1Interrupt( void)&lt;br /&gt;
 {&lt;br /&gt;
     // send data to PC every 10 ms (based on Timer1)&lt;br /&gt;
     char RS232_Out_Buffer[32];&lt;br /&gt;
     sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d\n&amp;quot;,X, Y, phi1, phi2);&lt;br /&gt;
     putsUART1(RS232_Out_Buffer);&lt;br /&gt;
 &lt;br /&gt;
     mLED_3_Toggle(); // toggle LED for feedback&lt;br /&gt;
     &lt;br /&gt;
     // clear interrupt flag and exit&lt;br /&gt;
     mT1ClearIntFlag();&lt;br /&gt;
 } // T1 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I2C Communication with DACs ===&lt;br /&gt;
&lt;br /&gt;
The two I2C ports were initialized above in the initInterruptComm() function.  The I2C communication also uses functions from the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]], found in chapter 15.  The general structure of the function is to send a series of commands to the DAC and wait for this to complete after each command.  First, the Start command is sent, then Idle waits until the I2C line is no longer busy.  Then the address of the chip on the I2C line is sent out and the PIC waits until the chip has acknowledged (ACKed).  This addressed is defined by the chips used as well as the configuration pins set when wiring the device up.  It then sends the command byte to tell the DAC to get ready to output data and finally it sends the data byte telling the DAC how much voltage to output.  The line is then closed to avoid sending extraneous data and the process is repeated for the second DAC.  This information will change depending on the device being interfaced with (particularly if the PIC has to switch from master to slave mode) but the basic principles outlined here can be used for most applications.&lt;br /&gt;
&lt;br /&gt;
 void MAX518(int force)&lt;br /&gt;
 {&lt;br /&gt;
     unsigned char addr = 0b01011000; // address of DAC on I2C line&lt;br /&gt;
     unsigned char cmd = 0x00; //command line &lt;br /&gt;
     int force1 = 127+(7-(force &amp;gt;&amp;gt; 4))*8; // upper nibble to motor 1&lt;br /&gt;
     int force2 = 127+(7-(force &amp;amp; 15))*8; // lower nibble to motor 2&lt;br /&gt;
    &lt;br /&gt;
     // Send to DAC 1 //////////////////////&lt;br /&gt;
     StartI2C1();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C1();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (addr); //address &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (cmd); //command line &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1(force1); //output &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C1();  //end of data send &lt;br /&gt;
     IdleI2C1();  //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     // Send to DAC 2 //////////////////////&lt;br /&gt;
     StartI2C2();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C2();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2 (addr); //address &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
       &lt;br /&gt;
     MasterWriteI2C2 (cmd); //command line &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2(force2); //output &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C2();  //end of data send &lt;br /&gt;
     IdleI2C2();  //Wait to complete &lt;br /&gt;
 }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
* Common ground - When connecting several circuit boards together, make sure they have a common ground.  If this is not done, the ground from one board can float relative to the other boards and cause problems when sending signals between boards.&lt;br /&gt;
* Current limitations - When using DC/DC converters, exceeding the maximum current may cause the converter voltage output to decrease.&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Impedance_matching Impedance matching] - As with all modular circuitry, make sure that the output impedance of one circuit is matched to the input of the connected circuit.&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17922</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17922"/>
		<updated>2010-03-19T03:15:56Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
Watch [http://www.youtube.com/watch?v=7j37NCYWHF8 Haptikos] (and the other projects) in action on YouTube.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible. The backboard of the pantograph is screwed into the bottom. The motors were held in place by a set of holes in the top plate and a second bracket suspended between the top and bottom. Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page for the TR-36, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC and read in on the timer pins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RS-232 Communication with PC ===&lt;br /&gt;
&lt;br /&gt;
We found that reliable communication between the different components of our system was one of the more challenging aspects of the project.  Because of this, we decided to post our code here as a quick reference.  The desired baud rates for serial (DESIRED_BAUDRATE) and I2C (BRG_VAL) communication were defined at the beginning of the code to be&lt;br /&gt;
&lt;br /&gt;
 #define DESIRED_BAUDRATE       19200      // The desired BaudRate RS-232&lt;br /&gt;
 #define Fsck   					50000 &lt;br /&gt;
 #define BRG_VAL    				((SYS_FREQ/2/Fsck)-2) &lt;br /&gt;
&lt;br /&gt;
This first function initializes the UART1 port on the PIC.  For an explanation of the configuration variables, and other UART functions, see chapter 16 of the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]].&lt;br /&gt;
&lt;br /&gt;
 void initUART1(int pbClk)&lt;br /&gt;
 {&lt;br /&gt;
     // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
     // Module Enable &lt;br /&gt;
     // Work in IDLE mode &lt;br /&gt;
     // Communication through usual pins &lt;br /&gt;
     // Disable wake-up &lt;br /&gt;
     // Loop back disabled &lt;br /&gt;
     // Input to Capture module from ICx pin &lt;br /&gt;
     // no parity 8 bit &lt;br /&gt;
     // 1 stop bit &lt;br /&gt;
     // IRDA encoder and decoder disabled &lt;br /&gt;
     // CTS and RTS pins are disabled &lt;br /&gt;
     // UxRX idle state is &amp;#039;1&amp;#039; &lt;br /&gt;
     // 16x baud clock - normal speed&lt;br /&gt;
     #define config1    UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
    &lt;br /&gt;
     // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
     // IrDA encoded UxTX idle state is &amp;#039;0&amp;#039;&lt;br /&gt;
     // Enable UxRX pin&lt;br /&gt;
     // Enable UxTX pin&lt;br /&gt;
     // Interrupt on transfer of every character to TSR &lt;br /&gt;
     // Interrupt on every char received&lt;br /&gt;
     // Disable 9-bit address detect&lt;br /&gt;
     // Rx Buffer Over run status bit clear&lt;br /&gt;
     #define config2      UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR   &lt;br /&gt;
  &lt;br /&gt;
     // Open UART2 with config1 and config2&lt;br /&gt;
     OpenUART1( config1, config2, SYS_FREQ/16/DESIRED_BAUDRATE-1);   // calculate actual BAUD generate value.&lt;br /&gt;
        &lt;br /&gt;
     // Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
     ConfigIntUART1(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next initialization function configures Timer1 which is used to generate an interrupt every 10 ms that sends location data to the PC.  The timer is configured to add one count every 64 clock cycles of the PIC with a priority of 7 (the highest value) as the feedback to the computer is important for rendering the game correctly.&lt;br /&gt;
&lt;br /&gt;
 void initInterruptComm()&lt;br /&gt;
 {&lt;br /&gt;
    // Initialize timer 1 to generate interrupt to send data to PC&lt;br /&gt;
    // init Timer1 mode and period (PR1) // produces 10ms period&lt;br /&gt;
    OpenTimer1( T1_ON | T1_PS_1_64 | T1_SOURCE_INT, 12499); &lt;br /&gt;
      &lt;br /&gt;
    mT1SetIntPriority(7);    // set Timer1 Interrupt Priority&lt;br /&gt;
    mT1ClearIntFlag();       // clear interrupt flag&lt;br /&gt;
    mT1IntEnable(1);         // enable timer1 interrupts&lt;br /&gt;
 &lt;br /&gt;
    // Initialize I2C lines to communicate data to DACs&lt;br /&gt;
    OpenI2C1( I2C_EN, BRG_VAL );&lt;br /&gt;
    OpenI2C2( I2C_EN, BRG_VAL );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then we create an interrupt handler for UART1 which is triggered when the PIC detects that there is data in the serial buffer.  This is set to a priority level of 2 because it is less important than sending location information to the PC.  The function ReadUART1 retrieves a single character from the serial buffer, use getsUART1() for strings.&lt;br /&gt;
&lt;br /&gt;
 // UART 1 interrupt handler&lt;br /&gt;
 // it is set at priority level 2&lt;br /&gt;
 void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned char force;&lt;br /&gt;
 &lt;br /&gt;
    // Is this an RX interrupt?&lt;br /&gt;
    if(mU1RXGetIntFlag()) {&lt;br /&gt;
         // Clear the RX interrupt Flag&lt;br /&gt;
         mU1RXClearIntFlag();&lt;br /&gt;
    &lt;br /&gt;
         force = ReadUART1(); // get data from PC&lt;br /&gt;
         mLED_0_Toggle(); // toggle LED for feedback&lt;br /&gt;
         MAX518(force); // send signal to motors&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // We don&amp;#039;t care about TX interrupt&lt;br /&gt;
    if ( mU1TXGetIntFlag() ) {&lt;br /&gt;
         mU1TXClearIntFlag();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We also create an interrupt controller for Timer1 to send location information back at a pre-defined rate.  The function uses putsUART1 which sends a string of data.&lt;br /&gt;
&lt;br /&gt;
 // interrput code for the timer 1&lt;br /&gt;
 void __ISR( _TIMER_1_VECTOR, ipl7) T1Interrupt( void)&lt;br /&gt;
 {&lt;br /&gt;
     // send data to PC every 10 ms (based on Timer1)&lt;br /&gt;
     char RS232_Out_Buffer[32];&lt;br /&gt;
     sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d\n&amp;quot;,X, Y, phi1, phi2);&lt;br /&gt;
     putsUART1(RS232_Out_Buffer);&lt;br /&gt;
 &lt;br /&gt;
     mLED_3_Toggle(); // toggle LED for feedback&lt;br /&gt;
     &lt;br /&gt;
     // clear interrupt flag and exit&lt;br /&gt;
     mT1ClearIntFlag();&lt;br /&gt;
 } // T1 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I2C Communication with DACs ===&lt;br /&gt;
&lt;br /&gt;
The two I2C ports were initialized above in the initInterruptComm() function.  The I2C communication also uses functions from the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]], found in chapter 15.  The general structure of the function is to send a series of commands to the DAC and wait for this to complete after each command.  First, the Start command is sent, then Idle waits until the I2C line is no longer busy.  Then the address of the chip on the I2C line is sent out and the PIC waits until the chip has acknowledged (ACKed).  This addressed is defined by the chips used as well as the configuration pins set when wiring the device up.  It then sends the command byte to tell the DAC to get ready to output data and finally it sends the data byte telling the DAC how much voltage to output.  The line is then closed to avoid sending extraneous data and the process is repeated for the second DAC.  This information will change depending on the device being interfaced with (particularly if the PIC has to switch from master to slave mode) but the basic principles outlined here can be used for most applications.&lt;br /&gt;
&lt;br /&gt;
 void MAX518(int force)&lt;br /&gt;
 {&lt;br /&gt;
     unsigned char addr = 0b01011000; // address of DAC on I2C line&lt;br /&gt;
     unsigned char cmd = 0x00; //command line &lt;br /&gt;
     int force1 = 127+(7-(force &amp;gt;&amp;gt; 4))*8; // upper nibble to motor 1&lt;br /&gt;
     int force2 = 127+(7-(force &amp;amp; 15))*8; // lower nibble to motor 2&lt;br /&gt;
    &lt;br /&gt;
     // Send to DAC 1 //////////////////////&lt;br /&gt;
     StartI2C1();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C1();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (addr); //address &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (cmd); //command line &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1(force1); //output &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C1();  //end of data send &lt;br /&gt;
     IdleI2C1();  //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     // Send to DAC 2 //////////////////////&lt;br /&gt;
     StartI2C2();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C2();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2 (addr); //address &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
       &lt;br /&gt;
     MasterWriteI2C2 (cmd); //command line &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2(force2); //output &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C2();  //end of data send &lt;br /&gt;
     IdleI2C2();  //Wait to complete &lt;br /&gt;
 }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=17921</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=17921"/>
		<updated>2010-03-19T03:14:56Z</updated>

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

		<summary type="html">&lt;p&gt;Philip Dames: /* Decoder Board */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page for the TR-36, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC and read in on the timer pins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RS-232 Communication with PC ===&lt;br /&gt;
&lt;br /&gt;
We found that reliable communication between the different components of our system was one of the more challenging aspects of the project.  Because of this, we decided to post our code here as a quick reference.  The desired baud rates for serial (DESIRED_BAUDRATE) and I2C (BRG_VAL) communication were defined at the beginning of the code to be&lt;br /&gt;
&lt;br /&gt;
 #define DESIRED_BAUDRATE       19200      // The desired BaudRate RS-232&lt;br /&gt;
 #define Fsck   					50000 &lt;br /&gt;
 #define BRG_VAL    				((SYS_FREQ/2/Fsck)-2) &lt;br /&gt;
&lt;br /&gt;
This first function initializes the UART1 port on the PIC.  For an explanation of the configuration variables, and other UART functions, see chapter 16 of the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]].&lt;br /&gt;
&lt;br /&gt;
 void initUART1(int pbClk)&lt;br /&gt;
 {&lt;br /&gt;
     // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
     // Module Enable &lt;br /&gt;
     // Work in IDLE mode &lt;br /&gt;
     // Communication through usual pins &lt;br /&gt;
     // Disable wake-up &lt;br /&gt;
     // Loop back disabled &lt;br /&gt;
     // Input to Capture module from ICx pin &lt;br /&gt;
     // no parity 8 bit &lt;br /&gt;
     // 1 stop bit &lt;br /&gt;
     // IRDA encoder and decoder disabled &lt;br /&gt;
     // CTS and RTS pins are disabled &lt;br /&gt;
     // UxRX idle state is &amp;#039;1&amp;#039; &lt;br /&gt;
     // 16x baud clock - normal speed&lt;br /&gt;
     #define config1    UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
    &lt;br /&gt;
     // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
     // IrDA encoded UxTX idle state is &amp;#039;0&amp;#039;&lt;br /&gt;
     // Enable UxRX pin&lt;br /&gt;
     // Enable UxTX pin&lt;br /&gt;
     // Interrupt on transfer of every character to TSR &lt;br /&gt;
     // Interrupt on every char received&lt;br /&gt;
     // Disable 9-bit address detect&lt;br /&gt;
     // Rx Buffer Over run status bit clear&lt;br /&gt;
     #define config2      UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR   &lt;br /&gt;
  &lt;br /&gt;
     // Open UART2 with config1 and config2&lt;br /&gt;
     OpenUART1( config1, config2, SYS_FREQ/16/DESIRED_BAUDRATE-1);   // calculate actual BAUD generate value.&lt;br /&gt;
        &lt;br /&gt;
     // Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
     ConfigIntUART1(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next initialization function configures Timer1 which is used to generate an interrupt every 10 ms that sends location data to the PC.  The timer is configured to add one count every 64 clock cycles of the PIC with a priority of 7 (the highest value) as the feedback to the computer is important for rendering the game correctly.&lt;br /&gt;
&lt;br /&gt;
 void initInterruptComm()&lt;br /&gt;
 {&lt;br /&gt;
    // Initialize timer 1 to generate interrupt to send data to PC&lt;br /&gt;
    // init Timer1 mode and period (PR1) // produces 10ms period&lt;br /&gt;
    OpenTimer1( T1_ON | T1_PS_1_64 | T1_SOURCE_INT, 12499); &lt;br /&gt;
      &lt;br /&gt;
    mT1SetIntPriority(7);    // set Timer1 Interrupt Priority&lt;br /&gt;
    mT1ClearIntFlag();       // clear interrupt flag&lt;br /&gt;
    mT1IntEnable(1);         // enable timer1 interrupts&lt;br /&gt;
 &lt;br /&gt;
    // Initialize I2C lines to communicate data to DACs&lt;br /&gt;
    OpenI2C1( I2C_EN, BRG_VAL );&lt;br /&gt;
    OpenI2C2( I2C_EN, BRG_VAL );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then we create an interrupt handler for UART1 which is triggered when the PIC detects that there is data in the serial buffer.  This is set to a priority level of 2 because it is less important than sending location information to the PC.  The function ReadUART1 retrieves a single character from the serial buffer, use getsUART1() for strings.&lt;br /&gt;
&lt;br /&gt;
 // UART 1 interrupt handler&lt;br /&gt;
 // it is set at priority level 2&lt;br /&gt;
 void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned char force;&lt;br /&gt;
 &lt;br /&gt;
    // Is this an RX interrupt?&lt;br /&gt;
    if(mU1RXGetIntFlag()) {&lt;br /&gt;
         // Clear the RX interrupt Flag&lt;br /&gt;
         mU1RXClearIntFlag();&lt;br /&gt;
    &lt;br /&gt;
         force = ReadUART1(); // get data from PC&lt;br /&gt;
         mLED_0_Toggle(); // toggle LED for feedback&lt;br /&gt;
         MAX518(force); // send signal to motors&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // We don&amp;#039;t care about TX interrupt&lt;br /&gt;
    if ( mU1TXGetIntFlag() ) {&lt;br /&gt;
         mU1TXClearIntFlag();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We also create an interrupt controller for Timer1 to send location information back at a pre-defined rate.  The function uses putsUART1 which sends a string of data.&lt;br /&gt;
&lt;br /&gt;
 // interrput code for the timer 1&lt;br /&gt;
 void __ISR( _TIMER_1_VECTOR, ipl7) T1Interrupt( void)&lt;br /&gt;
 {&lt;br /&gt;
     // send data to PC every 10 ms (based on Timer1)&lt;br /&gt;
     char RS232_Out_Buffer[32];&lt;br /&gt;
     sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d\n&amp;quot;,X, Y, phi1, phi2);&lt;br /&gt;
     putsUART1(RS232_Out_Buffer);&lt;br /&gt;
 &lt;br /&gt;
     mLED_3_Toggle(); // toggle LED for feedback&lt;br /&gt;
     &lt;br /&gt;
     // clear interrupt flag and exit&lt;br /&gt;
     mT1ClearIntFlag();&lt;br /&gt;
 } // T1 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I2C Communication with DACs ===&lt;br /&gt;
&lt;br /&gt;
The two I2C ports were initialized above in the initInterruptComm() function.  The I2C communication also uses functions from the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]], found in chapter 15.  The general structure of the function is to send a series of commands to the DAC and wait for this to complete after each command.  First, the Start command is sent, then Idle waits until the I2C line is no longer busy.  Then the address of the chip on the I2C line is sent out and the PIC waits until the chip has acknowledged (ACKed).  This addressed is defined by the chips used as well as the configuration pins set when wiring the device up.  It then sends the command byte to tell the DAC to get ready to output data and finally it sends the data byte telling the DAC how much voltage to output.  The line is then closed to avoid sending extraneous data and the process is repeated for the second DAC.  This information will change depending on the device being interfaced with (particularly if the PIC has to switch from master to slave mode) but the basic principles outlined here can be used for most applications.&lt;br /&gt;
&lt;br /&gt;
 void MAX518(int force)&lt;br /&gt;
 {&lt;br /&gt;
     unsigned char addr = 0b01011000; // address of DAC on I2C line&lt;br /&gt;
     unsigned char cmd = 0x00; //command line &lt;br /&gt;
     int force1 = 127+(7-(force &amp;gt;&amp;gt; 4))*8; // upper nibble to motor 1&lt;br /&gt;
     int force2 = 127+(7-(force &amp;amp; 15))*8; // lower nibble to motor 2&lt;br /&gt;
    &lt;br /&gt;
     // Send to DAC 1 //////////////////////&lt;br /&gt;
     StartI2C1();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C1();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (addr); //address &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (cmd); //command line &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1(force1); //output &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C1();  //end of data send &lt;br /&gt;
     IdleI2C1();  //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     // Send to DAC 2 //////////////////////&lt;br /&gt;
     StartI2C2();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C2();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2 (addr); //address &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
       &lt;br /&gt;
     MasterWriteI2C2 (cmd); //command line &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2(force2); //output &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C2();  //end of data send &lt;br /&gt;
     IdleI2C2();  //Wait to complete &lt;br /&gt;
 }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17877</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17877"/>
		<updated>2010-03-19T01:36:21Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Decoder Board */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page for the TR-36, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RS-232 Communication with PC ===&lt;br /&gt;
&lt;br /&gt;
We found that reliable communication between the different components of our system was one of the more challenging aspects of the project.  Because of this, we decided to post our code here as a quick reference.  The desired baud rates for serial (DESIRED_BAUDRATE) and I2C (BRG_VAL) communication were defined at the beginning of the code to be&lt;br /&gt;
&lt;br /&gt;
 #define DESIRED_BAUDRATE       19200      // The desired BaudRate RS-232&lt;br /&gt;
 #define Fsck   					50000 &lt;br /&gt;
 #define BRG_VAL    				((SYS_FREQ/2/Fsck)-2) &lt;br /&gt;
&lt;br /&gt;
This first function initializes the UART1 port on the PIC.  For an explanation of the configuration variables, and other UART functions, see chapter 16 of the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]].&lt;br /&gt;
&lt;br /&gt;
 void initUART1(int pbClk)&lt;br /&gt;
 {&lt;br /&gt;
     // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
     // Module Enable &lt;br /&gt;
     // Work in IDLE mode &lt;br /&gt;
     // Communication through usual pins &lt;br /&gt;
     // Disable wake-up &lt;br /&gt;
     // Loop back disabled &lt;br /&gt;
     // Input to Capture module from ICx pin &lt;br /&gt;
     // no parity 8 bit &lt;br /&gt;
     // 1 stop bit &lt;br /&gt;
     // IRDA encoder and decoder disabled &lt;br /&gt;
     // CTS and RTS pins are disabled &lt;br /&gt;
     // UxRX idle state is &amp;#039;1&amp;#039; &lt;br /&gt;
     // 16x baud clock - normal speed&lt;br /&gt;
     #define config1    UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
    &lt;br /&gt;
     // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
     // IrDA encoded UxTX idle state is &amp;#039;0&amp;#039;&lt;br /&gt;
     // Enable UxRX pin&lt;br /&gt;
     // Enable UxTX pin&lt;br /&gt;
     // Interrupt on transfer of every character to TSR &lt;br /&gt;
     // Interrupt on every char received&lt;br /&gt;
     // Disable 9-bit address detect&lt;br /&gt;
     // Rx Buffer Over run status bit clear&lt;br /&gt;
     #define config2      UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR   &lt;br /&gt;
  &lt;br /&gt;
     // Open UART2 with config1 and config2&lt;br /&gt;
     OpenUART1( config1, config2, SYS_FREQ/16/DESIRED_BAUDRATE-1);   // calculate actual BAUD generate value.&lt;br /&gt;
        &lt;br /&gt;
     // Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
     ConfigIntUART1(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next initialization function configures Timer1 which is used to generate an interrupt every 10 ms that sends location data to the PC.  The timer is configured to add one count every 64 clock cycles of the PIC with a priority of 7 (the highest value) as the feedback to the computer is important for rendering the game correctly.&lt;br /&gt;
&lt;br /&gt;
 void initInterruptComm()&lt;br /&gt;
 {&lt;br /&gt;
    // Initialize timer 1 to generate interrupt to send data to PC&lt;br /&gt;
    // init Timer1 mode and period (PR1) // produces 10ms period&lt;br /&gt;
    OpenTimer1( T1_ON | T1_PS_1_64 | T1_SOURCE_INT, 12499); &lt;br /&gt;
      &lt;br /&gt;
    mT1SetIntPriority(7);    // set Timer1 Interrupt Priority&lt;br /&gt;
    mT1ClearIntFlag();       // clear interrupt flag&lt;br /&gt;
    mT1IntEnable(1);         // enable timer1 interrupts&lt;br /&gt;
 &lt;br /&gt;
    // Initialize I2C lines to communicate data to DACs&lt;br /&gt;
    OpenI2C1( I2C_EN, BRG_VAL );&lt;br /&gt;
    OpenI2C2( I2C_EN, BRG_VAL );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then we create an interrupt handler for UART1 which is triggered when the PIC detects that there is data in the serial buffer.  This is set to a priority level of 2 because it is less important than sending location information to the PC.  The function ReadUART1 retrieves a single character from the serial buffer, use getsUART1() for strings.&lt;br /&gt;
&lt;br /&gt;
 // UART 1 interrupt handler&lt;br /&gt;
 // it is set at priority level 2&lt;br /&gt;
 void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned char force;&lt;br /&gt;
 &lt;br /&gt;
    // Is this an RX interrupt?&lt;br /&gt;
    if(mU1RXGetIntFlag()) {&lt;br /&gt;
         // Clear the RX interrupt Flag&lt;br /&gt;
         mU1RXClearIntFlag();&lt;br /&gt;
    &lt;br /&gt;
         force = ReadUART1(); // get data from PC&lt;br /&gt;
         mLED_0_Toggle(); // toggle LED for feedback&lt;br /&gt;
         MAX518(force); // send signal to motors&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // We don&amp;#039;t care about TX interrupt&lt;br /&gt;
    if ( mU1TXGetIntFlag() ) {&lt;br /&gt;
         mU1TXClearIntFlag();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We also create an interrupt controller for Timer1 to send location information back at a pre-defined rate.  The function uses putsUART1 which sends a string of data.&lt;br /&gt;
&lt;br /&gt;
 // interrput code for the timer 1&lt;br /&gt;
 void __ISR( _TIMER_1_VECTOR, ipl7) T1Interrupt( void)&lt;br /&gt;
 {&lt;br /&gt;
     // send data to PC every 10 ms (based on Timer1)&lt;br /&gt;
     char RS232_Out_Buffer[32];&lt;br /&gt;
     sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d\n&amp;quot;,X, Y, phi1, phi2);&lt;br /&gt;
     putsUART1(RS232_Out_Buffer);&lt;br /&gt;
 &lt;br /&gt;
     mLED_3_Toggle(); // toggle LED for feedback&lt;br /&gt;
     &lt;br /&gt;
     // clear interrupt flag and exit&lt;br /&gt;
     mT1ClearIntFlag();&lt;br /&gt;
 } // T1 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I2C Communication with DACs ===&lt;br /&gt;
&lt;br /&gt;
The two I2C ports were initialized above in the initInterruptComm() function.  The I2C communication also uses functions from the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]], found in chapter 15.  The general structure of the function is to send a series of commands to the DAC and wait for this to complete after each command.  First, the Start command is sent, then Idle waits until the I2C line is no longer busy.  Then the address of the chip on the I2C line is sent out and the PIC waits until the chip has acknowledged (ACKed).  This addressed is defined by the chips used as well as the configuration pins set when wiring the device up.  It then sends the command byte to tell the DAC to get ready to output data and finally it sends the data byte telling the DAC how much voltage to output.  The line is then closed to avoid sending extraneous data and the process is repeated for the second DAC.  This information will change depending on the device being interfaced with (particularly if the PIC has to switch from master to slave mode) but the basic principles outlined here can be used for most applications.&lt;br /&gt;
&lt;br /&gt;
 void MAX518(int force)&lt;br /&gt;
 {&lt;br /&gt;
     unsigned char addr = 0b01011000; // address of DAC on I2C line&lt;br /&gt;
     unsigned char cmd = 0x00; //command line &lt;br /&gt;
     int force1 = 127+(7-(force &amp;gt;&amp;gt; 4))*8; // upper nibble to motor 1&lt;br /&gt;
     int force2 = 127+(7-(force &amp;amp; 15))*8; // lower nibble to motor 2&lt;br /&gt;
    &lt;br /&gt;
     // Send to DAC 1 //////////////////////&lt;br /&gt;
     StartI2C1();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C1();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (addr); //address &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (cmd); //command line &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1(force1); //output &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C1();  //end of data send &lt;br /&gt;
     IdleI2C1();  //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     // Send to DAC 2 //////////////////////&lt;br /&gt;
     StartI2C2();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C2();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2 (addr); //address &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
       &lt;br /&gt;
     MasterWriteI2C2 (cmd); //command line &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2(force2); //output &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C2();  //end of data send &lt;br /&gt;
     IdleI2C2();  //Wait to complete &lt;br /&gt;
 }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17872</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17872"/>
		<updated>2010-03-19T01:30:52Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|550px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RS-232 Communication with PC ===&lt;br /&gt;
&lt;br /&gt;
We found that reliable communication between the different components of our system was one of the more challenging aspects of the project.  Because of this, we decided to post our code here as a quick reference.  The desired baud rates for serial (DESIRED_BAUDRATE) and I2C (BRG_VAL) communication were defined at the beginning of the code to be&lt;br /&gt;
&lt;br /&gt;
 #define DESIRED_BAUDRATE       19200      // The desired BaudRate RS-232&lt;br /&gt;
 #define Fsck   					50000 &lt;br /&gt;
 #define BRG_VAL    				((SYS_FREQ/2/Fsck)-2) &lt;br /&gt;
&lt;br /&gt;
This first function initializes the UART1 port on the PIC.  For an explanation of the configuration variables, and other UART functions, see chapter 16 of the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]].&lt;br /&gt;
&lt;br /&gt;
 void initUART1(int pbClk)&lt;br /&gt;
 {&lt;br /&gt;
     // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
     // Module Enable &lt;br /&gt;
     // Work in IDLE mode &lt;br /&gt;
     // Communication through usual pins &lt;br /&gt;
     // Disable wake-up &lt;br /&gt;
     // Loop back disabled &lt;br /&gt;
     // Input to Capture module from ICx pin &lt;br /&gt;
     // no parity 8 bit &lt;br /&gt;
     // 1 stop bit &lt;br /&gt;
     // IRDA encoder and decoder disabled &lt;br /&gt;
     // CTS and RTS pins are disabled &lt;br /&gt;
     // UxRX idle state is &amp;#039;1&amp;#039; &lt;br /&gt;
     // 16x baud clock - normal speed&lt;br /&gt;
     #define config1    UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
    &lt;br /&gt;
     // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
     // IrDA encoded UxTX idle state is &amp;#039;0&amp;#039;&lt;br /&gt;
     // Enable UxRX pin&lt;br /&gt;
     // Enable UxTX pin&lt;br /&gt;
     // Interrupt on transfer of every character to TSR &lt;br /&gt;
     // Interrupt on every char received&lt;br /&gt;
     // Disable 9-bit address detect&lt;br /&gt;
     // Rx Buffer Over run status bit clear&lt;br /&gt;
     #define config2      UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR   &lt;br /&gt;
  &lt;br /&gt;
     // Open UART2 with config1 and config2&lt;br /&gt;
     OpenUART1( config1, config2, SYS_FREQ/16/DESIRED_BAUDRATE-1);   // calculate actual BAUD generate value.&lt;br /&gt;
        &lt;br /&gt;
     // Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
     ConfigIntUART1(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The next initialization function configures Timer1 which is used to generate an interrupt every 10 ms that sends location data to the PC.  The timer is configured to add one count every 64 clock cycles of the PIC with a priority of 7 (the highest value) as the feedback to the computer is important for rendering the game correctly.&lt;br /&gt;
&lt;br /&gt;
 void initInterruptComm()&lt;br /&gt;
 {&lt;br /&gt;
    // Initialize timer 1 to generate interrupt to send data to PC&lt;br /&gt;
    // init Timer1 mode and period (PR1) // produces 10ms period&lt;br /&gt;
    OpenTimer1( T1_ON | T1_PS_1_64 | T1_SOURCE_INT, 12499); &lt;br /&gt;
      &lt;br /&gt;
    mT1SetIntPriority(7);    // set Timer1 Interrupt Priority&lt;br /&gt;
    mT1ClearIntFlag();       // clear interrupt flag&lt;br /&gt;
    mT1IntEnable(1);         // enable timer1 interrupts&lt;br /&gt;
 &lt;br /&gt;
    // Initialize I2C lines to communicate data to DACs&lt;br /&gt;
    OpenI2C1( I2C_EN, BRG_VAL );&lt;br /&gt;
    OpenI2C2( I2C_EN, BRG_VAL );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then we create an interrupt handler for UART1 which is triggered when the PIC detects that there is data in the serial buffer.  This is set to a priority level of 2 because it is less important than sending location information to the PC.  The function ReadUART1 retrieves a single character from the serial buffer, use getsUART1() for strings.&lt;br /&gt;
&lt;br /&gt;
 // UART 1 interrupt handler&lt;br /&gt;
 // it is set at priority level 2&lt;br /&gt;
 void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned char force;&lt;br /&gt;
 &lt;br /&gt;
    // Is this an RX interrupt?&lt;br /&gt;
    if(mU1RXGetIntFlag()) {&lt;br /&gt;
         // Clear the RX interrupt Flag&lt;br /&gt;
         mU1RXClearIntFlag();&lt;br /&gt;
    &lt;br /&gt;
         force = ReadUART1(); // get data from PC&lt;br /&gt;
         mLED_0_Toggle(); // toggle LED for feedback&lt;br /&gt;
         MAX518(force); // send signal to motors&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    // We don&amp;#039;t care about TX interrupt&lt;br /&gt;
    if ( mU1TXGetIntFlag() ) {&lt;br /&gt;
         mU1TXClearIntFlag();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We also create an interrupt controller for Timer1 to send location information back at a pre-defined rate.  The function uses putsUART1 which sends a string of data.&lt;br /&gt;
&lt;br /&gt;
 // interrput code for the timer 1&lt;br /&gt;
 void __ISR( _TIMER_1_VECTOR, ipl7) T1Interrupt( void)&lt;br /&gt;
 {&lt;br /&gt;
     // send data to PC every 10 ms (based on Timer1)&lt;br /&gt;
     char RS232_Out_Buffer[32];&lt;br /&gt;
     sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d\n&amp;quot;,X, Y, phi1, phi2);&lt;br /&gt;
     putsUART1(RS232_Out_Buffer);&lt;br /&gt;
 &lt;br /&gt;
     mLED_3_Toggle(); // toggle LED for feedback&lt;br /&gt;
     &lt;br /&gt;
     // clear interrupt flag and exit&lt;br /&gt;
     mT1ClearIntFlag();&lt;br /&gt;
 } // T1 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== I2C Communication with DACs ===&lt;br /&gt;
&lt;br /&gt;
The two I2C ports were initialized above in the initInterruptComm() function.  The I2C communication also uses functions from the [[Introduction_to_the_PIC32#Further_Reading|Peripheral Library Guide]], found in chapter 15.  The general structure of the function is to send a series of commands to the DAC and wait for this to complete after each command.  First, the Start command is sent, then Idle waits until the I2C line is no longer busy.  Then the address of the chip on the I2C line is sent out and the PIC waits until the chip has acknowledged (ACKed).  This addressed is defined by the chips used as well as the configuration pins set when wiring the device up.  It then sends the command byte to tell the DAC to get ready to output data and finally it sends the data byte telling the DAC how much voltage to output.  The line is then closed to avoid sending extraneous data and the process is repeated for the second DAC.  This information will change depending on the device being interfaced with (particularly if the PIC has to switch from master to slave mode) but the basic principles outlined here can be used for most applications.&lt;br /&gt;
&lt;br /&gt;
 void MAX518(int force)&lt;br /&gt;
 {&lt;br /&gt;
     unsigned char addr = 0b01011000; // address of DAC on I2C line&lt;br /&gt;
     unsigned char cmd = 0x00; //command line &lt;br /&gt;
     int force1 = 127+(7-(force &amp;gt;&amp;gt; 4))*8; // upper nibble to motor 1&lt;br /&gt;
     int force2 = 127+(7-(force &amp;amp; 15))*8; // lower nibble to motor 2&lt;br /&gt;
    &lt;br /&gt;
     // Send to DAC 1 //////////////////////&lt;br /&gt;
     StartI2C1();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C1();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (addr); //address &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1 (cmd); //command line &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C1(force1); //output &lt;br /&gt;
     IdleI2C1(); &lt;br /&gt;
     while( !I2C1STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C1();  //end of data send &lt;br /&gt;
     IdleI2C1();  //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     // Send to DAC 2 //////////////////////&lt;br /&gt;
     StartI2C2();   //Send the Start Bit (begin of data send) &lt;br /&gt;
     IdleI2C2();    //Wait to complete &lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2 (addr); //address &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
       &lt;br /&gt;
     MasterWriteI2C2 (cmd); //command line &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     MasterWriteI2C2(force2); //output &lt;br /&gt;
     IdleI2C2(); &lt;br /&gt;
     while( !I2C2STATbits.ACKSTAT==0 ) {}&lt;br /&gt;
 &lt;br /&gt;
     StopI2C2();  //end of data send &lt;br /&gt;
     IdleI2C2();  //Wait to complete &lt;br /&gt;
 }  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17779</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17779"/>
		<updated>2010-03-18T17:23:57Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|550px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Debugging Tips ==&lt;br /&gt;
&lt;br /&gt;
While working on the project, as with all mechatronics projects, we ran into many small problems.  We will highlight some of the most common ones so that you don&amp;#039;t make the same mistakes that we did and can spend more time improving, rather than fixing, your project.&lt;br /&gt;
&lt;br /&gt;
* ALWAYS CHECK YOUR WIRING - When using a breadboard wires often get knocked loose, break off, etc.  The thing we spent the most time on was trying to debug circuits where a wire had simply come out of the breadboard or that we had put back in the wrong place.  Don&amp;#039;t waste your time reading the I2C signals on an oscilloscope to make sure that the data is correct only to find out you accidentally wired the data line to the clock pin of your chip.  And remember that the multimeter is your friend; when dealing with lots of ribbon cables it is invaluable for checking if pins are wired correctly.&lt;br /&gt;
* Use the oscilloscope - While the multimeter is good for checking some things, it missed quick voltage changes that a scope will let you see.  We used this for 95% of our debugging, from checking power lines to reading the individual bits being sent over I2C or RS-232 lines.&lt;br /&gt;
* Check your soldering - Make sure the solder on any solder board, PCB&amp;#039;s, or the PIC board is done correctly.  This tends to wear out over time and can break loose/come into contact with other connections creating shorts.  If your circuit is not working, check this as it only requires a short visual inspection but can save hours of headache from changing software and tracing wires all over your circuit boards.&lt;br /&gt;
* Remember how your circuit is supposed to work - After we built the power amp PCBs we were testing them to make sure they work.  Since they are current control circuits, the motor + and motor - pins must have current flowing between them or the output voltage will float.  We forgot to put a power resistor between these pins and spent a long time trying to figure out why the output was not changing before we finally realized it actually did work exactly as it was designed to.&lt;br /&gt;
* Use sockets when moving your circuit to solder board - If a chip burns out and you have soldered it directly to the board, it takes a long time to remove.  Use sockets instead as this makes changing chips very easy.  The same goes for data lines, use pin headers and ribbon cables instead of soldering your cables directly to the board.  This also makes moving the circuit much simpler as it can be disassembled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17771</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17771"/>
		<updated>2010-03-18T17:02:00Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Next Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|550px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17769</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17769"/>
		<updated>2010-03-18T17:01:44Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|550px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.  However, using our platform, all it takes is a creative mind and some programming knowledge to develop a wide variety of other games/demonstrations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;br /&gt;
&lt;br /&gt;
The most fun aspect to this project is that using the basic system we have developed, (while there is room for improvement) a wide variety of interactive demonstrations and games can be developed.  The foundations for communication, the mechanical platform, and all of the necessary circuitry are in place so all that is needed is a creative mind and some programming knowledge.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17767</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17767"/>
		<updated>2010-03-18T16:57:33Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Haptikos.jpg|thumb|right|550px]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering BS/MS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;br /&gt;
&lt;br /&gt;
The most fun aspect to this project is that using the basic system we have developed, (while there is room for improvement) a wide variety of interactive demonstrations and games can be developed.  The foundations for communication, the mechanical platform, and all of the necessary circuitry are in place so all that is needed is a creative mind and some programming knowledge.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17766</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17766"/>
		<updated>2010-03-18T16:48:36Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Next Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|550px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|400px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;br /&gt;
&lt;br /&gt;
The most fun aspect to this project is that using the basic system we have developed, (while there is room for improvement) a wide variety of interactive demonstrations and games can be developed.  The foundations for communication, the mechanical platform, and all of the necessary circuitry are in place so all that is needed is a creative mind and some programming knowledge.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Circut1Team22meg.jpg&amp;diff=17765</id>
		<title>File:Circut1Team22meg.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Circut1Team22meg.jpg&amp;diff=17765"/>
		<updated>2010-03-18T16:37:44Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: uploaded a new version of &amp;quot;Image:Circut1Team22meg.jpg&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Circut2Team22meg.jpg&amp;diff=17764</id>
		<title>File:Circut2Team22meg.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Circut2Team22meg.jpg&amp;diff=17764"/>
		<updated>2010-03-18T16:36:19Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: uploaded a new version of &amp;quot;Image:Circut2Team22meg.jpg&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Circut2Team22meg.jpg&amp;diff=17762</id>
		<title>File:Circut2Team22meg.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Circut2Team22meg.jpg&amp;diff=17762"/>
		<updated>2010-03-18T16:35:32Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: uploaded a new version of &amp;quot;Image:Circut2Team22meg.jpg&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Circut1Team22meg.jpg&amp;diff=17761</id>
		<title>File:Circut1Team22meg.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Circut1Team22meg.jpg&amp;diff=17761"/>
		<updated>2010-03-18T16:33:39Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: uploaded a new version of &amp;quot;Image:Circut1Team22meg.jpg&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17759</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17759"/>
		<updated>2010-03-18T16:32:12Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Further Reading */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|550px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|400px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|400px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
There are several areas for improvement in our project, the primary one being to improve the haptic feedback by allowing forces to be generated in arbitrary directions and increasing the resolution of forces we can generate.  The first half of this involves debugging the Jacobian calculations and ensuring that all data types in the calculations are compatible (i.e., multiply ints by ints instead of floats).  For the second half of this, we need more reliable serial communication from the PC to the PIC.  While we were successful sending a single byte of data, when trying to send a string of data (2 or 4 bytes) the PIC would often, though not not always, fail to receive the data.  Fixing this, the full capabilities of the DAC could be used to have 256 levels of forcing instead of the 16 we used.  This would be helpful when trying to simulate textures, compliant objects, stickiness (damping), etc, all of which should be possible with a device such as Haptikos.  This could be a benefit to games, such as feeling more resistance when your character walks through a patch of mud instead of over grass.&lt;br /&gt;
&lt;br /&gt;
There are also a couple of improvements for the mechanical design.  The Pittman motors used had a &amp;quot;clickiness&amp;quot; to them so as the user moved the pantograph around they felt slightly bumps in the motion, even when the motors were unpowered.  While this may actually be a benefit for some applications (i.e., simulating rough surfaces), in general we would recommend choosing motors with a smoother feel to them.  Also, when mounting the capstan drive system, take care to properly align all parts.  Not centering the arcs properly can lead to increased resistance and can limit the size of the workspace.  We ran into this issue with the initial build but fixed it for the final design.&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17652</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17652"/>
		<updated>2010-03-18T05:55:26Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|600px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17651</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17651"/>
		<updated>2010-03-18T05:54:49Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|600px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:HapticsBlockDiagram.png|thumb|600px|center|Block diagram of circuit.]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|300px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:HapticsBlockDiagram.png&amp;diff=17650</id>
		<title>File:HapticsBlockDiagram.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:HapticsBlockDiagram.png&amp;diff=17650"/>
		<updated>2010-03-18T05:52:47Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17649</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17649"/>
		<updated>2010-03-18T05:51:54Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|600px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17648</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17648"/>
		<updated>2010-03-18T05:51:19Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|600px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The five boards created to run Haptikos &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05 DC/DC converter] that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518 DAC] chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001 op-amps], as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
&lt;br /&gt;
This circuit uses current feedback in order to maintain a constant output current, allowing for direct torque control of the motors.  This circuit was designed by Prof. Peshkin and detailed information can be found [http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm here].  Two of these boards were used, one for each motor with the input coming from the DAC board and power from the central breakout board.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17647</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17647"/>
		<updated>2010-03-18T05:47:27Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|600px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The five boards created to run Haptikos &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
We used the [[Introduction_to_the_PIC32|PIC32MX460F512L]] from Microchip on the NU32 board.  The board was powered using a USB cable plugging into the socket on the left side of the board.  The ribbon cable on the far right of the breadboard connects to the breakout board and has four I2C lines, four lines from the decoding circuit, +5V, and ground.  The cable next to it is the RS-232 that connects the PIC to the PC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[image:PictureofCircut2Team22.jpg|x200px|right]]&lt;br /&gt;
&lt;br /&gt;
This board serves as a central hub for all of the other components to the circuit, allowing for only one ribbon cable to connect to the PIC&amp;#039;s breadboard.  Clockwise from the green power supply board, we have connections to the two power amplification circuits, the PIC breadboard, the decoding circuit, and the DAC/level shifting circuit.  The power supply provides a separate +5V, -5V, and ground line to power the motors, protecting the PIC from the high amperage needed to drive the motors.  In the center of the board is a [http://pdf1.alldatasheet.com/datasheet-pdf/view/303507/RSG/EC2A05.html Cincon EC2A05] DC/DC converter that takes in the +/- 5V lines and outputs +/- 15V used for the level shifting circuit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC/Level Shifter Board ===&lt;br /&gt;
&lt;br /&gt;
This board takes the force data sent over I2C from the PIC (from the PC) and creates an analog voltage signal ranging from +/- 5V that feeds into the power amplification circuit.  Here, we use a [http://www.alldatasheet.com/datasheet-pdf/pdf/73533/MAXIM/MAX518.html MAX518] DAC chip that connects to a level shifting circuit using 2 [http://pdf1.alldatasheet.com/datasheet-pdf/view/70235/LINER/LT1001.html LT1001] op-amps, as shown in the circuit diagram.  This is necessary to allow the motors to spin in both directions without the use of PWM (which we opted not to use because we want torque, and thus, current control).  Note the actual board consists of two identical channels, one for each motor, while the schematic shows only one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
The decoding circuit reads the signals from two optical encoders them into up and down counts (two each) that connect to the timer pins on the PIC.  The encoders used are Canon TR-1 (equivalent to [http://www.usa.canon.com/industrial_encoders/lre_tr36.html TR-36]) which are 3600 counts per revolution using x1 decoding.  The decoding circuit is that used in the Recommended Receiving Circuit link at the bottom of the page, where the channels first feed into a [http://pdf1.alldatasheet.com/datasheet-pdf/view/27890/TI/SN74HC14N.html SN74HC14N Schmitt trigger] which cleans up the signals going into the [http://pdf1.alldatasheet.com/datasheet-pdf/view/71312/LSI/LS7083.html LS7083 quadrature decoding] chips.  These take the pulse trains and translate them into up and down counts which are then sent over to the PIC.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|right]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
how it controls it&lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|right]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|right]]&lt;br /&gt;
|}&lt;br /&gt;
This circuit uses current feedback to maintain a constant output current to get a constant stall torque from the motor.&lt;br /&gt;
And there is the link of the PCB&lt;br /&gt;
http://www.mech.northwestern.edu/courses/433/Writeups/MotorAmp/motoramp.htm&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17627</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17627"/>
		<updated>2010-03-18T05:02:18Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|600px|Pantograph.]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The five boards created to run Haptikos &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
&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;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|thumb|400px|center]]&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:PictureofCircut2Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC Board ===&lt;br /&gt;
&lt;br /&gt;
what it does&lt;br /&gt;
&lt;br /&gt;
its circuit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
what it does &lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
how it controls it&lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|center]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17626</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17626"/>
		<updated>2010-03-18T05:01:46Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos began as a modification of the pantograph used by John Glassmire for finger position tracking for his M.S. thesis work in friction-based tactile displays.  This design allows the free point to move in a (roughly) semi-circular area in a plane.  Two optical encoders are mounted at the shoulder joints to track the angle of the upper arm links (and thus the finger).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately track finger position, but could not put apply any sort of haptic feedback.  To add this capability, we chose to use a capstan drive system.  In such a system, there is a thread spooled onto the motor shaft that winds in and out depending on how the motor is spinning.  This thread is mounted to another element that is pulled back and forth as the thread spools out.  Such drive systems can be found in other haptic devices (such as these [http://eduhaptics.org/index.php/HapticDevices/HapticPaddles haptic paddles]) and are chosen because they increase the torque of a motor as a gearhead does, but avoid problems such as backlash which is a major concern when the goal is to provide smoothly changing forces to a user.  The motors chosen for out project were the [[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|Pittman 700935]] motors, which are relatively powerful motors without a gearhead. &lt;br /&gt;
&lt;br /&gt;
The arc of the capstan drive was created by milling two 2.75&amp;quot; radius arcs out of Aluminum.  A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the motor, the thread was tightly wound around the spool (3/8&amp;quot; diameter brass cylinder, mounted with a set screw) three times and pulled taut in the groove.  The spool was covered with a plastic layer to increase the coefficient of friction between the spool and the thread.  The gear ratio created by our drive system is 44 : 3 (&amp;lt;math&amp;gt; = r_{arc}/r_{spool}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[Image:EncodersTeam22.jpg|thumb|center|600px]]&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Box ===&lt;br /&gt;
&lt;br /&gt;
To enclose the entire system, we made a 12&amp;quot; x 12&amp;quot; x 3&amp;quot; acrylic box using the laser cutter.  The top plate is removable so that the circuitry is readily accessible and holes were cut to create a mount for the pantograph and motors.  A second bracket was also cut to hold the pantograph and motors in place, which was mounted inside the box, and holes were cut in the bottom of the box to allow the pantograph to be screwed into the base plate.  Holes were cut in the side and back of the box to allow wires to pass in and out of the box.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The five boards created to run Haptikos &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
&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;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|thumb|400px|center]]&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:PictureofCircut2Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC Board ===&lt;br /&gt;
&lt;br /&gt;
what it does&lt;br /&gt;
&lt;br /&gt;
its circuit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
what it does &lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
how it controls it&lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|center]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17602</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17602"/>
		<updated>2010-03-18T04:27:23Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* The Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos is a modification from a previous pentagraph configuration. This allows for the free point to be able to freely move in a fixed two-dimensional plane. There are two Canon TR-36 optical encoders with a 3600 count/rev in x1 mode mounted on top of the stationary pivot.(see below) They are used to track the angle of the larger bars and calculate the position of the free point.&lt;br /&gt;
&lt;br /&gt;
[[Image:EncodersTeam22.jpg|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately tell where the free point was in space, but could not put any force on that point.  &lt;br /&gt;
[[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|A Pittman 700935 motor]] was attached to each of the larger bars in the back of the pantograph using a capstan configuration. &lt;br /&gt;
&lt;br /&gt;
The capstan was created by milling two arcs out of Aluminum and then attaching one arc end to the furthest point from the backboard on each bar. A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the Motor, the thread was merely wound around the shaft three times and replaced tight into the groove. (see below) &lt;br /&gt;
&lt;br /&gt;
The gear ratio the arc applies to the motor is approximately 14.7 to 1. (Radius of arc/ Radius of Capstan Drive)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The five boards created to run Haptikos &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
&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;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|thumb|400px|center]]&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:PictureofCircut2Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC Board ===&lt;br /&gt;
&lt;br /&gt;
what it does&lt;br /&gt;
&lt;br /&gt;
its circuit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
what it does &lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
how it controls it&lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|center]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17600</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17600"/>
		<updated>2010-03-18T04:26:49Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* The Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|left|600px]]&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos is a modification from a previous pentagraph configuration. This allows for the free point to be able to freely move in a fixed two-dimensional plane. There are two Canon TR-36 optical encoders with a 3600 count/rev in x1 mode mounted on top of the stationary pivot.(see below) They are used to track the angle of the larger bars and calculate the position of the free point.&lt;br /&gt;
&lt;br /&gt;
[[Image:EncodersTeam22.jpg|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately tell where the free point was in space, but could not put any force on that point.  &lt;br /&gt;
[[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|A Pittman 700935 motor]] was attached to each of the larger bars in the back of the pantograph using a capstan configuration. &lt;br /&gt;
&lt;br /&gt;
The capstan was created by milling two arcs out of Aluminum and then attaching one arc end to the furthest point from the backboard on each bar. A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the Motor, the thread was merely wound around the shaft three times and replaced tight into the groove. (see below) &lt;br /&gt;
&lt;br /&gt;
The gear ratio the arc applies to the motor is approximately 14.7 to 1. (Radius of arc/ Radius of Capstan Drive)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The five boards created to run Haptikos &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
&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;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|thumb|400px|center]]&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:PictureofCircut2Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC Board ===&lt;br /&gt;
&lt;br /&gt;
what it does&lt;br /&gt;
&lt;br /&gt;
its circuit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
what it does &lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
how it controls it&lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|center]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17599</id>
		<title>Haptic Gaming System</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Haptic_Gaming_System&amp;diff=17599"/>
		<updated>2010-03-18T04:25:34Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|right|500px]]&lt;br /&gt;
&lt;br /&gt;
Haptikos is an interactive gaming system that allows the user to physically feel a virtual world.  The player controls the cursor on screen by moving the red joystick attached to the linkage system.  Two games were created to highlight the capabilities of the feedback system.  The first involves feeling a virtual shape displayed on the screen (the display can be toggled off if you want more of a challenge).  This game is a simple demonstration of translating a virtual environment into something physical.  The second is a side-scrolling level where the player collects jewels while avoiding boxes.  This shows possible applications to an interactive gaming environment, where the user can directly feel what is happening to their character on screen.&lt;br /&gt;
&lt;br /&gt;
==The Team==&lt;br /&gt;
&lt;br /&gt;
*Yang Bai (Mechatronics Masters Student)&lt;br /&gt;
*Philip Dames (Mechanical Engineering MS/BS)&lt;br /&gt;
*Megan Welker(Mechanical Engineering BS/BM)&lt;br /&gt;
&lt;br /&gt;
[[Image:Team22haptics.jpg|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=== Existing System ===&lt;br /&gt;
Haptikos is a modification from a previous pentagraph configuration. This allows for the free point to be able to freely move in a fixed two-dimensional plane. There are two Canon TR-36 optical encoders with a 3600 count/rev in x1 mode mounted on top of the stationary pivot.(see below) They are used to track the angle of the larger bars and calculate the position of the free point.&lt;br /&gt;
&lt;br /&gt;
[[Image:EncodersTeam22.jpg|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
=== System Modifications ===&lt;br /&gt;
&lt;br /&gt;
The existing system had the capability to accurately tell where the free point was in space, but could not put any force on that point.  &lt;br /&gt;
[[Actuators_Available_in_the_Mechatronics_Lab#Pittman_700935_motor_with_500_line_encoder|A Pittman 700935 motor]] was attached to each of the larger bars in the back of the pantograph using a capstan configuration. &lt;br /&gt;
&lt;br /&gt;
The capstan was created by milling two arcs out of Aluminum and then attaching one arc end to the furthest point from the backboard on each bar. A piece of heavy duty thread was set into the groove of the outer side of the arc and secured by screws on either side. To connect the capstan to the Motor, the thread was merely wound around the shaft three times and replaced tight into the groove. (see below) &lt;br /&gt;
&lt;br /&gt;
The gear ratio the arc applies to the motor is approximately 14.7 to 1. (Radius of arc/ Radius of Capstan Drive)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:ArchTeam22.jpg|thumb|300px|Arc.|center]]&lt;br /&gt;
|[[image:MotorThreadTeam22.jpg|thumb|400px|Thread and Motor attachment.|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The five boards created to run Haptikos &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Overall.png|thumb|400px|center]]&lt;br /&gt;
|[[image:CircuitsTeam22.jpg|thumb|400px|Circuitry.|center]]&lt;br /&gt;
&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;
&lt;br /&gt;
=== PIC Configuration ===&lt;br /&gt;
&lt;br /&gt;
[[Image:PICWiringTeam22.jpg|thumb|400px|center]]&lt;br /&gt;
&lt;br /&gt;
=== Breakout Board ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:PictureofCircut2Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DAC Board ===&lt;br /&gt;
&lt;br /&gt;
what it does&lt;br /&gt;
&lt;br /&gt;
its circuit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut1Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Decoder Board ===&lt;br /&gt;
&lt;br /&gt;
what it does &lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:Circut2Team22meg.jpg|x200px|center]]&lt;br /&gt;
|[[image:2PictureofCircut1Team22.jpg|x200px|center]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Motor Control Board ===&lt;br /&gt;
how it controls it&lt;br /&gt;
&lt;br /&gt;
its circuit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|[[image:MotorControlCircutTeam22.png|x200px|center]]&lt;br /&gt;
|[[image:PictureofMotorControlCircutTeam22.jpg|x200px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mathematical Analysis of the Pantograph ==&lt;br /&gt;
&lt;br /&gt;
There are two parts to this problem, the forward kinematics and the force generation, which are duals of each other.  &lt;br /&gt;
&lt;br /&gt;
=== Forward Kinematics ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:pantographDimensions.png|right]]&lt;br /&gt;
The forward kinematics of a system (typically a robotic arm or something similar) is often used in robotics and gaming to calculate the position and orientation of a hand given the joint angles of an arm.  The idea is to create a function such that &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt; where &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is a vector giving the location of the finger and &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt; is a vector of the joint angles (here the angles read by the encoders).  For our system, the pantograph used was originally designed and build by John Glassmire (formerly of the Laboratory of Intelligent Mechanical Systems.  Dimensions as well as full calculations of the forward kinematics may be found in Appendix D and Solidworks drawings of the parts found in Appendix E of the paper found at [http://lims.mech.northwestern.edu/papers/glassmire06/GlassmireMaster.pdf].  Encoder 1 is found at angle 1, encoder 2 at angle 5, and the finger at angle 3, with arrows indicating the direction of positive motion, note that angle 5 is backwards to provide reflectional symmetry about the vertical axis.&lt;br /&gt;
&lt;br /&gt;
=== Force Generation ===&lt;br /&gt;
&lt;br /&gt;
Obviously, the wider the range of forces we can create, both in terms of magnitude and direction, the better sensation we are able to create with Haptikos.  However, we also want to transition between forces in such a way that feels natural to the user.  These are fundamental issue addressed by designers for any haptic device.  There is a limit to the torques our motors can provide (current supply to each motor is limited to 500 mA), and thus on the strength of the forces we can give to the user and the resolution of these forces was also limited by communication issues (as discussed later).  &lt;br /&gt;
&lt;br /&gt;
We independently confirmed the forward kinematic calculations, and through a series of substitutions, put them all into a single function &amp;lt;math&amp;gt;x=f(\theta)&amp;lt;/math&amp;gt;.  Taking the derivative of this mapping, we have that &amp;lt;math&amp;gt;\dot{x} = \frac{df}{d\theta} \dot{\theta} = J(\theta) \dot{\theta}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;J(\theta)&amp;lt;/math&amp;gt; is the Jacobian of the map.  By the duality of velocity and force, we have that the torques required to produce a given force can be found using the relation &amp;lt;math&amp;gt;\tau = J(\theta)^T F&amp;lt;/math&amp;gt;.  For our map, the Jacobian is complicated and would take up nearly a page so it is omitted for brevity.  However, we were unsuccessful using this approach to generate forces in arbitrary directions.  This may be due to many causes, from data types conflicting to omitting a sign or term when typing out the equations.&lt;br /&gt;
&lt;br /&gt;
Instead we used simple controls to achieve forcing in eight directions.  A single byte of data was sent to the PIC containing the motor control information, with the first nibble to control motor 1 and the second to control motor 2.  This allows for 16 levels of forcing, with 7 chosen to indicate zero force.  Less than 7 provided a torque along the positive direction for each angle (as indicated in the figure) and greater than 7 along the negative direction.  We found that activating both motors allowed us to create forces along the y and x axis (depending on if the motors were providing a torque in the same, or opposite, directions, respectively) while only activating a single motor provided forcing along the lines y = x and y = -x (motor 2 or motor 1, respectively).  This range of 16 discrete force values was mapped over half of the possible force range because we found that having forces that were too strong caused for large jumps when the forces changed direction while smaller forces allowed for smoother-feeling transitions, at the cost of a more rigid feeling to surfaces.&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
&lt;br /&gt;
=== PIC Programing ===&lt;br /&gt;
&lt;br /&gt;
All PIC programming was done in C using the MPLAB IDE by Microchip Technologies.&lt;br /&gt;
To install MPLAB, follow the instructions found [[Getting_Started_with_PIC32#Software|here]].&lt;br /&gt;
To create a new project in MPLAB, follow the instructions found [[HelloWorld PIC32#Create_a_New_Project|here]].&lt;br /&gt;
The source files for our project can be downloaded [[Media:hapticInterfaceSourceCode.zip|here]]&lt;br /&gt;
(remember to change the include directions if you are trying to use our MPLAB project files).&lt;br /&gt;
&lt;br /&gt;
While the source code is commented, here is a list of the project-specific files and a brief summary of the contents of each.&lt;br /&gt;
* fingerTrack.c - This is the main file of the project, containing the main function as well as initialization and communication functions&lt;br /&gt;
** initEncoder - This initializes the 4 timers (T2CK - T5CK) used to count the up and down pulses from the [[Haptic_Gaming_System#Decoder|decoding circuit]].  Timers 2 and 3 are for the up and down counts of encoder 1, respectively.  Timers 4 and 5 are used for up and down counts of encoder 2.&lt;br /&gt;
** getEncoderPositionX - This reads the current counts of encoder X and updates the angles, checking for rollover of the 16-bit counters.&lt;br /&gt;
** initUART1 - This initializes the UART1 bus of the PIC to be used for RS-232 communication with the PC.&lt;br /&gt;
** initInterruptComm - This initializes the Timer1 interrupt to run every 10ms and initializes both I2C buses on the PIC to talk to the DAC&amp;#039;s.  The interrupt timing could be synched to match the frame rate of the game, but we found this to be reliable and not interfere with the data transmission interrupt.&lt;br /&gt;
** MAX518 - This takes the data sent from the PC about how to force the system, parses the data, and sends out the appropriate signal to the DAC&amp;#039;s over the I2C buses.  Only 1 byte of data is sent between the PC and the PIC as this was found to be the most reliable, though it does limit the resolution of forces we are able to achieve (16 levels instead of 256).  We did not find this to be a problem, but is one area of possible improvement.&lt;br /&gt;
** UART1 interrupt - When it detects that it has received data from the PC, the PIC will read the data, call the MAX518 function, and toggle LED0 for visual feedback.  We had some issues with the interrupt not functioning correctly after the game was reset after a game over (this did not happen every time).&lt;br /&gt;
** Timer1 interrupt - This sends the current (x,y) position of the finger as well as the two angles of the encoders to the PC.&lt;br /&gt;
* calculations.c (and .h) - This library has the functions used to calculate the forward kinematics of the pantograph (i.e., to get finger position from the encoder readings).&lt;br /&gt;
** sine and cosine - These functions take in the current encoder angle (measured to the nearest tenth of a degree) as an integer and use a lookup table to calculate the sine.  The output is an integer which must be divided by 10000 (the global variable SCALER).  This was done to speed up calculations as it only involves integer math instead of floats, and can directly use encoder counts instead of converting these to radians.&lt;br /&gt;
** forwardKinematics - This calculates the current (x,y) location of the finger based on the current encoder readings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Game Programming ===&lt;br /&gt;
&lt;br /&gt;
The games are programmed and run in the Processing language (find out more information [[Processing|here]]).  We chose to make two games that highlight different aspects of our project, though as you can imagine, our system could be used for many more.&lt;br /&gt;
&lt;br /&gt;
====Link&amp;#039;s Adventure ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:LinksAdventureTeam22.jpg|right|x300px|alt=Screen shot of the game.]]&lt;br /&gt;
This game is a side-scrolling adventure game where the player must avoid the blocks and collect the jewels scrolling across the screen.  As the player icon, we chose to use the character Link from the original Legend of Zelda game due to the simple graphics and game style.  The three types of jewels each have a different effect on the game.  Red replenish health lost from hitting the boxes, green increase the score, and blue slow blocks (whose speed gradually increases over time). When Link runs into a red block, Haptikos will shake the joystick as the box disappears to give the user a physical indication that their player was injured, much like the rumble feature found in many modern game console controllers.  While the user has the option of going for a high score, we have found that it is generally more enjoyable to simply run into the blocks as this is the unique part of our device.  Future iterations of this game would include some sort of haptic feedback when a jewel is collected to the player strikes the ground, possibly even simulating gravity by pushing the character towards the ground.  Commented source code can be found [[Media:zeldaGame.zip|here]] and code allowing the game to be played with a computer mouse [[Media:zeldaGameMouse.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Identification Game ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:IdentiyGame.jpg|right|x300px|alt=Screen shot of the Identification game, in this case the user will feel a square.]]&lt;br /&gt;
In this game the player will feel a virtual shape (circle, star, triangle, square, or diamond) in the center of the screen.  When the cursor (blue circle) hits the shape, the device will push the finger away from the shape, creating the sensation that you are feeling a wall.  The player can also play blindly, using only the feedback from Haptikos to attempt to identify the invisible shape.  To toggle this mode, press the &amp;#039;i&amp;#039; key on the keyboard.  Press &amp;#039;r&amp;#039; to generate a new shape at random.  Currently there are only 5 shapes, chosen because they are different enough so that the user can identify the shape (i.e., a heptagon and an octagon would be too similar to identify using the discrete forces available to us).  Commented source code can be found [[Media:indentifyGame.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:HapticInterfaceSourceCode.zip&amp;diff=17582</id>
		<title>File:HapticInterfaceSourceCode.zip</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:HapticInterfaceSourceCode.zip&amp;diff=17582"/>
		<updated>2010-03-18T04:10:37Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:PICWiringTeam22.jpg&amp;diff=17564</id>
		<title>File:PICWiringTeam22.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:PICWiringTeam22.jpg&amp;diff=17564"/>
		<updated>2010-03-18T03:13:29Z</updated>

		<summary type="html">&lt;p&gt;Philip Dames: uploaded a new version of &amp;quot;Image:PICWiringTeam22.jpg&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Philip Dames</name></author>
	</entry>
</feed>