Wednesday, December 9, 2009

Final Project-

Team 5
Daniel Dimoski
Colin Foe-Parker
Ramya Iyer

The semester is coming to an end. Snow is in the forecast and it is crunch time. We have been tasked to develop a "haptic instrument." A device that not only makes sound, but also imparts "feel" to the user. As Prof. Gillespie keeps mentioning, electronics are taking over. However, people are loosing the ability to connect with objects. This project is an attempt to remedy this trend. We want to combine the relatively boundless opportunities that electronics and software present with the feel, touch, and react experiences that are dominant in the physical world. By combining these two domains, new and better devices will undoubtedly develop.

Team Five, (Dan Colin and Ramya), has decided to do something novel. While we are pushing the bounds of the electric / physical interface we might as well push the boundaries farther and create something completely new. (Rather than imitating an instrument already in existance) So, we have been throwing ideas around. A lot of our inspirations so far have come from stringed instruments from multiple continents and cultures.


Musical System:

(A little farther in our design process....)
For our instrument, we decided on combining many of the individual elements that we learned in class. Specifically how to utilize, fader motors, H-bridges, microprocessors, Pure Data, Mosfets, encoders, motor models, multifaceted tinkering, and countless other skills. As stated above, our plan is to create something completely new that plays to the strengths of electronics; flexibility. How, do we provide flexibility, you ask? We make a hardware system that is easily adjusted to the sounds, feels, strengths and desires of the performer. Our hardware system consists of three motorized fader sliders as well as a haptic wheel/stick. The relation of these four inputs can provide the response necessary for a satisfactory experience as well as the flexibility of software.

Required Parts:

Our Project used some pretty sophisticated hardware. We used three fader motors. For those of you who don't know, Fader motors use a linear potentiometer to discern location of a tab along the track. By hooking the potentiometer in series with a 10K resistor a voltage divider is created. The location of the slider can be found by measuring the voltage at the middle node of the divider with an Analog to Digital Converter. These devices also have a small rotary motor/belt drive. This provides actuation to the device. Combine this with a control algorithm and the fader is set for haptic feedback.
We used a hefty dc motor as the primary haptic medium. Using a Pololu supplied current sensing chip, we were able to invoke a high gain proportional feedback loop to control torque. We coupled the current information with the bi-directional flexibility provided by a H-bridge. This gave us the ability to control the "feel" and "direction" of the experience. As our "metric," we measured the stall torque of the motor to be .74676 N-m. This torque proved to be sufficient to generate an adequate feedback to user input. While also not proving dangerous for the user if misused. The motor, however, was not ideal for this application. The motor had a relatively high moment of inertia as well as coarse gradation on the commutator. As a result, precise control of the device's torque was difficult.
To determine the rotor's position, we used an 8 bit (512 position) encoder attached to the rear of the motor. This provided .70 degree resolution. The granularity of the encoder was not ideal. It was a primary reason that instability developed when attempting to create a virtual wall.
The final component of our device was an ATmega 1280 microprocessor hidden in the form of an Arduino Mega. The Arduino was the brains of the operation. It ran off on a 10 millisecond interrupt driven loop. The Arduino was in charge of determining the state of all the sensors and implementing the correct feedback of the actuators. Additionally, the Arduino sent MIDI signals out to the a computer running PureData.

Case Fabrication:

We used the laser cutter in the AutoLab grad shop to cut the intricate shapes required to make these wooden cases for our project. An Auto CAD file of the required parts was drafted and than saved as a dxf file. A really neat color coding method was used to differentiate the correct cutting sequence and laser intensity. See pictures below. Some common designs for the larger electric motor stand were superimposed upon each other, in different colors, and then during the cutting process some color coded parts were called upon while others were left dormant.

The other wooden components of the cases were cut using traditional methods; then fastened together with nails, screws, and glue. Each case was designed with adequate space to allow for the concealment of the circuit boards and the Arduino Mega.



Software:

The arduino environment makes software development on a micro controller extremely easy. It does this by providing simple api's to control hardware functions. The downside is that it is often difficult to discern exactly what low level changes can be made without detrimentally affecting the operation of the device. And for our project... we needed to make some of those afore mentioned changes. We implemented a round robin software architecture running every 10 ms off an internal interrupt. The interrupt was fired every time Timer 0 (an 8 bit timer) overflowed. We had to do some low level register manipulation to make this happen as well as searching through the Arduino development files to see the side effects of our changes. The two most apparent changes were to the millis() and delay() functions. (An example of the unfortunate side effects mentioned earlier)

We also implemented two other hardware driven interrupts: one for both channels of the encoder. Upon seeing a rising edge on either of the encoder channels, the arduino would pause and increment/decrement the encoder count. The ability to discern discrete time increments as well as position measurements allowed us to determine the velocity of the haptic wheel. With the combination of position, velocity, and torque measurements, we have created a device that can easily implement a multitude of virtual environments.

During our development we implemented a couple test virtual environments. Particularly we demonstrated, mass springs, mass dampers, virtual walls, and pure springs. These environments were implemented in an attempt to discern exactly what feelings were reproducible using our hardware/software skills. Although we could "identify" the specific feelings of all of the aforementioned environments, we found that a couple hardware limitations resulted in non-ideal behaviours. Those limitations were the 16 Mhz clock speed of the ATmega 1280, the motor inertia, and the encoder resolution. These three elements made the most difference when trying to implement an "analog" feel using digital circuitry.

Sound Production with PureData (PD):

PureData is a powerful software which can be easily interfaced with other platforms like the Arduino or Labview. We used a Midi box to hook up the Arduino to PD. The circuit diagram and basic program to send signals from Arduino to PD can be found at http://itp.nyu.edu/physcomp/Labs/MIDIOutput.

In its simplest form, PD generates a sine wave to produce a note of a desired pitch and volume from computer/attached speakers. Manipulating the waveform in different ways changes the way the sound is perceived. People can distinguish between two instruments playing the same note based on the timbre of the note. For example, one can add "partials" to the fundamental frequency by multiplying it with some integer and adding the overtone to the output. The presence or absence of overtones or subharmonics is one of the characteristics of the sound produced by any instrument. Another important characteristic would be the attack, decay, sustain and release times (ADSR) of the note. PD can thus be used to create a variety of sounds by manipulating these parameters.

The arduino code as well as the Pure Data spreadsheet are included at the bottom of the post.


The Instrument:

We programmed our extremely flexible instrument to behave as either a gong or a virtual musical spring for demo day.

The gong feature was developed by implementing a horizontal virtual wall with the large motor. When the lever is rotated as to to hit the virtual wall/gong a signal is sent from the arduino to PD to initiate the sound. The wall behaves just as a drum head would. If the mallet is forced deep into the wall it will be repelled with a larger torque. Thus bouncing it back away from the object. An additional feature that we took advantage of was the instability that arises at the wall. Due to our coarse sensor resolution, we were unable to model an analog world using a digital one. So, as the user applies continuous force into the wall the system explodes; resulting in reverberations at the wall that are very similar to drum rolls. So, the system models discrete hits as well as continuous drum actions.

To imitate the sound of a gong, we used a reverberator available as one of the examples in PD.

We used the fader motors to control the volume and pitch of the device. The volume is varied by moving fader motor 2. The pitch was modulated by moving fader motor 3, which has a virtual spring feeling bringing it back to an equilibrium position at the bottom of the potentiometer. The feedback on fader motor 3 allows the musician to feel the slider's position by allow the cognitive understanding of the position.

An important design aspect for this device was the effect of the haptic feedback. We wanted to develop a system where physical feedback wasn't merely extraneous information for the human to sift through. Instead, it would be necessary in order to really master the device. We succeeded. It is almost impossible to to play this instrument without the virtual wall. Believe me, we tried. Additionally, during our demo day we asked some people to try the device w/ and w/o the feedback. The response was unanimous that the wall was "required" in order to make the device feasible to learn, play, or master.

As stated before, our other incentive was to develop a device that was flexible. So, as an afterthought we put in a "second instrument." By moving fader 1 we are able to switch between the haptic instruments.

The virtual spring is played using all the same hardware. However, the feel of the device changed drastically. The large motor no longer represented a drum head. Instead, by rotating the lever past the virtual equilibrium point it acted like a spring. In a very appropriate manner (for a spring that is), we accompanied the feel with an eerie wawa tone. The wawa frequency is varied by rotating the mallet further past the equilibrium point. So, more generated spring force accompanied a slower wawa frequency. This sound was generated by using frequency modulation. Rotating the lever would change the modulation index. Fader motors 2 and 3 accompanied the instrument and fulfilled the same function as in the gong.

At the Expo:

Our musical device is unlike any other that our audience had played before, because of that no one instinctively knew how to pick up and play. However, the same could be true for all instruments. A novice cannot play a violin without squeaking the first time. A novice will not be able to discern all the slide positions required to play a trombone. It is from practice, feel, and experience that these devices have become mastered. Our device too, will require time. However, the gong has the physical and auditory responses necessary to make a truly "learn-able" device.



Future Work:
This device could be improved. The biggest shortcoming was the limited sounds that we could generate with PureData. (The limited sounds are due to our inexperience with the software, not the limitations of the software itself.) So, developing a larger ensemble of virtual instruments that can be played along with the gong and virtual spring would be fun.




/*
Colin Foe Parker
Daniel Dimoski
Ramya Iyer

This Code Controls the big haptic motor....
*/
#define encoder0PinA 2
#define encoder0PinB 3
#define DirectionPin 52
#define CurrentPin 6
#define Motor1PWMPin 13
#define ledPinGreen 24
#define ledPinYellow 22
#define FaderPin1 7
#define FaderPin2 2
#define FaderPin3 3
#define FaderMosPin1 8
#define FaderMosPin2 9
#define FaderMosPin3 10

/////////////////////////////////////////////////////////////
//Variable Declarations
volatile uint16_t gTickCount = 0; //For Interrupt Timing
volatile uint8_t prevCount = 0; //For Interrupt Timing
volatile uint16_t timer=0;

volatile uint16_t encoder0Pos = 32768;
volatile int16_t Torque = 0;
unsigned int Direction=0;
uint16_t count=0;
uint8_t count2=30;
unsigned int tmp_Pos = 1;
unsigned int valx;
unsigned int valy;
unsigned int valz;
unsigned int analogValue;
int Print;
int16_t Lastencoder;
boolean A_set,enable;
boolean B_set;
int16_t speed1;
int16_t Fader1=0;
int16_t Fader2=0;
int16_t Fader3=0;
uint8_t modulation;
uint16_t note,gongvol;



////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
Serial2.begin(31250);
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
pinMode(ledPinGreen,OUTPUT);
pinMode(ledPinYellow,OUTPUT);

// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
pinMode(DirectionPin,OUTPUT);
}

////////////////////////////////////////////////////////////
//This loop will run ever 10 ms off a Timer0 overflow interrupt
void loop() {
Fader1=analogRead(FaderPin1);
note=(uint16_t)((Fader3-353)*.12+40);
speed1= (int16_t)(encoder0Pos-Lastencoder)*12.27;
Lastencoder=encoder0Pos;
analogValue = analogRead(CurrentPin) - 99;
Fader2=analogRead(FaderPin2);
Fader2=(uint16_t)((Fader2-353)*.4);
Fader3=analogRead(FaderPin3);
modulation=(uint8_t)(encoder0Pos-32768);
if (modulation > 200) modulation = 200;
if (Fader1 > 505) {
if ((count%40)==0){
digitalWrite(ledPinGreen,HIGH);
digitalWrite(ledPinYellow,LOW);
}
if ((count%80)==0){
digitalWrite(ledPinGreen,LOW);
digitalWrite(ledPinYellow,HIGH);
}
SpringDamper();
noteOn(0x91,note,Fader2);
noteOn(0x92,modulation,0);

}else{
note=(uint16_t)((Fader3-353)*.12+50);
virtualspring(FaderMosPin3,353,Fader3);
Print=VirtualWallBig(0);
//The flashing lights
if ((count%20)==0){
digitalWrite(ledPinGreen,HIGH);
digitalWrite(ledPinYellow,LOW);
}
if ((count%40)==0){
digitalWrite(ledPinGreen,LOW);
digitalWrite(ledPinYellow,HIGH);
}
if(enable ==1){
noteOn(0x90,note,Fader2);
noteOn(0x91,0,0);
enable =0;
}
gongvol=0;
}
//The Serial Stuff
if ((count%20)==0){
Serial.print(" Encoder Pos");
Serial.print(encoder0Pos);
Serial.print(" Note ");
Serial.print(note );
Serial.print(" GongVol ");
Serial.print(gongvol);
Serial.print(" Count1 ");
Serial.print(count);
Serial.print(" Fader 1 ");
Serial.print(Fader1);
Serial.print(" Fader 2 ");
Serial.print(Fader2);
Serial.print(" Fader 3 ");
Serial.print(Fader3);
Serial.print(" Speed ");
Serial.println(speed1);
}

count ++;

if (count ==10001){count = -1;}
WaitForTimer0Rollover();
}

/////////////////////////////////////////////////////////
//Functions
//Gong Function
uint8_t Gong(void){
uint8_t gongvalue;
gongvalue = (uint8_t)((speed1/150)*127);
return(gongvalue);
}
//Waits for the timer to roll over (10 ms)
void WaitForTimer0Rollover( void )
{
prevCount = gTickCount;
while ( gTickCount == prevCount )
{
;
}
} // WaitForTimer0Rollover

//To send notes to the midi
void noteOn(byte cmd, byte data1, byte data2) {
Serial2.print(cmd, BYTE);
Serial2.print(data1, BYTE);
Serial2.print(data2, BYTE);
}

//Virtual Springs for the Fader Motors
void virtualspring(int Channel, int ZeroPoint, int x) {
float TorqueFader;
float k = 3;

TorqueFader = (uint8_t) (x-ZeroPoint)*k;
if ((x-353)<20){ torquefader =" 0;"> 32768){
Temp_Power= (int16_t)(.5*(encoder0Pos-32768));
Direction = 0;
}else {
Temp_Power= (int16_t)(.5*(32768-encoder0Pos));
Direction = 1;
}
digitalWrite(DirectionPin,Direction);
TorqueControl(analogValue, Temp_Power);
}

// Code to translate the voltage control to torque control (Max Current ~250)
void TorqueControl(uint16_t Current, uint16_t DesiredCurrent){
float Pgain = 40;
if (DesiredCurrent > 350){
DesiredCurrent = 350;
}
Torque += Pgain*(DesiredCurrent-Current);
if (Torque < torque =" 0;"> 255){
Torque = 255;
}
analogWrite(Motor1PWMPin,Torque);
}

//Code to do a Virual Wall for the Big Motor
int VirtualWallBig(uint16_t Setpoint2){
int16_t Temp_Power;
float Pgain = 20;
float Dgain = .01;
Setpoint2 += 32768;
Temp_Power =(int16_t) ( Pgain*(encoder0Pos-Setpoint2))-Dgain*speed1;
if (encoder0Pos > Setpoint2) {
digitalWrite(DirectionPin,0);
}else{
Temp_Power = 0;
}
TorqueControl(analogValue, Temp_Power);
return(Temp_Power);
}

//Code to do a Virtual Spring Mass for the Big Motor
int16_t VirtualSpringMassBig(int Setpoint,float frequency){
static unsigned int counter=0;
int Temp_Power;
Temp_Power=(int16_t) (encoder0Pos-32768)*cos((counter-Setpoint)*frequency/(2*PI));
if (Temp_Power > 0){
Direction = 0;
}else {
Direction = 1;
Temp_Power = -Temp_Power;
}
counter ++;
digitalWrite(DirectionPin,Direction);
TorqueControl(analogValue,Temp_Power);
return(Temp_Power);
}

/*Quad Code taken from http://www.arduino.cc/playground/Main/RotaryEncoders
Interrupt on A changing state*/
void doEncoderA(){
// Low to High transition?
if (digitalRead(encoder0PinA) == HIGH) {
A_set = true;
if (!B_set) {
encoder0Pos = encoder0Pos + 1;
if (encoder0Pos >32760 && encoder0Pos < gongvol="abs(speed1);" enable="1;" a_set =" false;" b_set =" true;" encoder0pos =" encoder0Pos">32760 && encoder0Pos < gongvol="abs(speed1);" enable ="1;" b_set =" false;">

Wednesday, November 11, 2009

Lab 6: Project Exploratory and Non-parametric Sys ID

Team 5

Daniel Dimoski
Colin Foe-Parker
Ramya Iyer


1) Compare theoretical and experimental frequency response plots by placing traces on the same axes. Show these for you your low-pass Filter.






2) Document the makeup and construction of your system of interest in schematics, block diagrams, drawings, pictures, and words.


We decided not to embroil ourselves in the nightmare of serial communications with the Arduino. Instead we took the high, and oft just as frustrating road of using LabView. We set up a .vi that would output a sinusoid with noise while simultaneously reading in one analog channel using the Daq. (Look at figure 1) Additionally we used Advance Motion Control's 12A8 analog amplifier in voltage control mode. (Sadly, all we used the Arduino for was a 5V reference supply)We initially attempted using the H-bridge provided in class using a square wave output. However, labview was being tempermental and refused to update the duty cycle in any interval other than 10%.... Which would provide too granular of an input for our needs.







Figure 1: VI Backpanel view

The Physical wiring of our system was pretty simple. The hardest part was trying to figure out what channels corresponded to which pins on the Daq. Additionally, we did the experiment over a couple day period... so every time we would leave someone would take our setup apart. And the Daq or our redone wiring never seemed to behave quite as it had before until we either restarted the computer or fiddled with connections for half an hour...
We tested the white noise principle on two separate systems. System 1 was a RC lowpass circuit. Since it had no moving parts we thought that it would be easier to generate a valid and repeatable system id. Please look at Figure 2 for wiring guides... After that test we moved onto a real system.... the fader motor. An interesting thing occured though.... When exciting it with a sinusoid, the motor tended to pick new locations to vibrate around at each frequency. We attempted to rerun the system until we got a uniform center point. However, that was not really possible. This can explain why our data does not behave quite as expected. This result is a function of limitiations of the system.






Figure 2: Arduino as a 5V reference.... ooooooh awwww

Video1: Test of the RC Signal.... Pretty boring. Just a sinusoid


Video 2: Test of the Fader Motor. .
3) Show your experimental frequency response plot for your system of interest. If a parametric model can be fit to the data, show this parametric model with an additional set of traces on the same axes.



Wednesday, October 21, 2009

Lab 4: A Haptic Interface for Musical Expression

Team members for Lab 4:

John George

Huai-Ning Chang

Michael Woon

Goals:

The objectives for this lab include testing new Hall-Effect sensor with virtual spring and virtual damper, use Op Amp as differentiators, and building a haptic musical instrument with MIDI interface.

Accomplishments:

Comparing the performance of new Hall-Effect sensor to the old one, it was found out that new Hall-Effect sensor was more powerful than the old one. Unfortunately, our new Hall-Effect sensor blew out by accidentally shorting the pins, so basically we completed our lab with the old Hall-Effect sensor, amplified through the Op Amp.

The implementation of the Op Amp increased the analog signal range to the Arduino controller, improved resolution, and reduced chattering. Unfortunately, as we were about to use the Op Amp as a differentiator, our old Hall Effect sensor started acting erratically (see below). But the Op Amp circuit we designed and tried to implement is shown as the modeled system in Matlab. There was a final step that we did not actually do, and that was to put a gain on the output by ~1000.



To build a haptic musical instrument from analog input, we first made a file for Pd to read MIDI signals from Arduino. Different notes come by writing serial data from 30 to 90, with the appropriate nibbles (ex. 0x90). The Arduino programming code is as follows:

const int LEDpin = 13;
const int Sensor1Pin = 1;
const int den = 8;
// Variables:
byte note = 0;
// The MIDI note value to be played

void setup() {

// Set MIDI baud rate:
Serial.begin(31250);

pinMode(LEDpin, OUTPUT);
}

void loop() {
// play notes from F#-0 (30) to F#-5 (90):

note = analogRead(Sensor1Pin)/den;

//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):

noteOn
(0x90, note, 0x45);

digitalWrite
(LEDpin, HIGH);

delay(10);

//Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
noteOn
(0x90, note, 0x00);

digitalWrite
(LEDpin, LOW);
delay(10);
}

// plays a MIDI note. Doesn't check to see that

// cmd is greater than 127, or that data values are less than 127:

void noteOn(byte cmd, byte data1, byte data2) {

Serial.print(cmd, BYTE);

Serial.print(data1, BYTE);
Serial.print(data2, BYTE);

}


Unfortunately, after the new Hall-Effect sensor got shorted, our old Hall-Effect sensor started acting erratically, sometimes getting stuck at max output voltage. We could power down and power up the sensor and it would work, but eventually it started producing a constant 2.4V output. With no other sensor hooked up to our motor, we had to improvise and come up with another input sensor for the human (which unfortunately did not provide active force-feedback). Our instrument schematic is shown below.



By connected to MIDI and with the circuit, we can play different notes by applying different force to the sensor. Following is a video of the concert:



Just a note about using the force pad: Earlier we used to force pad to modulate volume in the Theremin Lab, and we found that it worked very well. It had great response and could easily be learned. In this lab, we used the force pad to modulate pitch, and we found that did not work as well as, say, a sliding potentiometer or some sort of position-based input. The force required to sustain higher notes was uncomfortable, the resolution was too high so it was easy to miss notes, and you always have to "ramp up" to the note you want.

Thursday, October 15, 2009

Lab 3B - Frequency Response and Virtual Environments

Objective: The objective of this lab was to implement variuos virtual environments using our iTouch motor and the Arduino software.

More simulations: We modified our earlier version of the motor simulation and replaced the current-controlled H-bridge witha simpler amplifier model that assumed rejection of back-emf effcts. This basically meant that we could get rid of one of the feedback loops and represent our model as such:



We found the transfer function of our system to be:



The corresponding Bode plot of this plant is:

After creating a Bode plot of our system, we injected sinusoids of various frequency into our system and recorded the response displacement. Note that the sinusoidal displacement of the motor (red) has a phase shift when compared to the input signal (blue). If one cycle = 2*pi, we found that the phase shift was approximately 1.51 radians, or 86.4 degrees. The frequency of our input signal was 0.2 Hz, so this phase shift corresponds with our Bode plot.


Virtual Haptic evironments:

This was one of the coolest parts of the project wherein we were supposed to replicate the feel of mechanical elements on our i touch motor.

Virtual Spring: In this exercise our aim was to introduce programmable changes to make the i touch motor feel like a spring. We used the position sensor to implement this environment. Based on the position readings from the hall effect sensor, a translation formula is applied to make the range of readings symmetrical on both sides of the center position of the armature. The program is tweaked to make the pwm value higher as the armature moves out on either side of the center position. This makes the user feel that the armature has stronger tendency to bounce back as he/she is moving it out further and hence it acts as a virtual spring!

We had initial hiccups in this exercise wherein we were able to replicate the spring feel on one side but not the other.. It was happening because of a negative pwm feedback on one side which when corrected behaved exactly as anticipated.

Virtual Wall

This was relatively simple environment to simulate once we got the virtual spring working. One position on either side of the center is chosen arbitrarily as the "wall" and the program is modified to make the motor go really stiff at those positions. We have a very high pwm value at this junction in the code which makes the armature vibrate insanely if one tried to force it beyond that point which makes the Virtual wall!!
Virtual Damper and Virtual spring-mass

A derivative control is applied in the code to get the virtual damper simulation. The concept is based on the theory that the armature should make the user feel variable resistances depending upon the applied speed on the armature. We collect the position of hall sensor every 50 ms and then calculate the velocity from that array of readings. This velocity reading is then used to control the virtual environment of the damper using the principle: the higher the velocity, higher is the impedance experienced by the user. We did implement the program for virtual damper but are not completely sure if we could replicate the feel. It was kind of difficult to sense damping if there was any and we were not able to judge objectively.

Due to time constraints, we were not able to simulate the virtual spring-mass system.


The most rewarding environment, we felt was the virtual spring. The force did increase in a linear fashion in the program and we could feel that increment in force as the armature is pushed on either side. The easiest to simulate was a virtual wall which was kind of fun too. You felt like you have just been electrocuted because the fingers start vibrating due to the offered resistance by the motor! The most difficult to feel was the virtual damper as damping was too subtle to feel. It was not a challenge from programming point of view but it was certainly hard to feel the damping. Maybe that is because of the low resolution of the hall effect sensor..




Lab 3 - Overview

Overview:
The first thing we did was construct our iTouch motor. We decided to control our motor using the Arduino. We determined the physical and electrical properties of the motor, such as the motor constant, resistance, motor inertia and damping. We simulated our model using Simulink in MATLAB.

Motor Assembly:

The motor was constructed out of laser cut pieces of wood, magnetic wire, screws, and extremely hefty magnets. A picture of the semi complete motor is embedded below. The motor is not a traditional rotary motor. Instead it has ~70 degrees of motion. (A reliable commutator is kinda hard to make.)
The construction steps were incredibly easy, thanks to Hasan's hard preparatory work. The hardest part of assembly was winding the motor with ~ 114 winds of magnetic wire. (The windings are hidden behind the magnets. After that, all the parts fit into their spots relatively easily. Construction instructions can be found on the cTools site....

Motor Instrumentation:

Since this motor is not rotary it is relatively useless without some form of sensory input for position control. (Otherwise is is constantly at the edge stops...) To attain sensory control we put a Hall Effect sensor and magnet combination onto the frame. As the spindle moves the magnetic field would change and we would get a position reading. Sadly, the magnetic field generated was extremely low. We were only able to get a gradation of ~ 13 values on our 10 bit ADC. That resulted in ~ 7 degrees of travel per each adc reading value. This, as well as timing issues, would come to haunt us when we tried to implement a position controller.

We also attempted to set up a current sensor. A current sensor would allow us to perceive/control how much torque was being output by the system. This is because T=I*Km. The current sensor was a chip from Pololu that gave ~150 mV per each amp of current flowing through our motor. We initially thought that this value would be sufficient. However, our motor did not draw much current. So, once again the resolution on our ADC lead to issues when attempting torque control.
Simulation:
We modeled our motor as shown in the block diagram below:
For our model, we needed to find the values for the resistance R, moment of inertia J, motor constant Km, and motor damping b. We used a multimeter to determine the resistance of the motor windings and found that R = 10.1Ohms.

We found the moment of inertia by suspending the armature of the motor with two threads equidistant from the center of mass. We aligned the threads so the motor armature was level to the ground and provided a small torque about the vertical axis. We recorded the time it took for the motor armature to complete ten oscillations and used the equations of motion of a bifilar pendulum to calculate the moment of inertial. We found that J = 4.11e-5 kg m^2.

At first we found the damping of the motor bearings to be extremely high and we would not get even a single oscillation of the motor armature. However, after oiling the bearings significantly, we noticed that the motor armature completed about 2-3 full oscillations before coming to a stop. We also noted the amplitudes of the each oscillation, so we can use the logarithmic decrement equations to find the damping ratio zeta. We found that zeta = 0.015 and b = wn*zeta*2 = 0.368, where wn is the natural frequency of the pendular motor armature, determined by wn = sqrt(g/l).

To find the motor constant, Km, we applied several torques to the motor (by handing weights of known mass from it) and measuring the current the motor is drawing. Using this method, we found Km = 0.105.

Plugging these values into our model, and using a Kp=1, tauL = 0 and iDes = 1, we found our theta over time:

This output makes sense, since our motor is simulated as a simple rotary motor. This means that with a constant current input, it will rotate and theta will increase at a constant slope. However, it takes time to get up to speed, which is shown in the figure above. Note how quickly it manages to do so.

A better way of looking at our step response is by looking at the change in theta over time:

Proportional Control:


We implemented a very elementary P control on position. Using the Hall Effect Sensor and an adjustable target point we were able to tune the system so that it would reside there. As discussed earlier... our sensor inputs had extremely coarse resolution. Additionally, our controller had no sense of "real time." (We didn't implement a interrupt routine to guarantee timely and consistent execution of code) As such, the system tended to vibrate in place a lot. Additionally, we could feel definitive torque impulses when holding the rotor. These impulses could be from the coarse nature of the timing loop or that the electrical system does not completely filter the pwm input. As such, the torque would flicker. We also noted that using the serial port was an extremely expensive operation. The timing loop was slowed down a lot when that occurred; resulting in wider oscillations... more hectic responses... and a worse behaving system. Look at the video below!









Lab 3: DC Motor Control - Introduction

Project Goal: The goal of this lab is to construct our own iTouch motor and use a hall effect sensor, power supply and H-bridge amplifier to control it and simulate several haptic virtual environments.

Team members: Colin Foe Parker, Piyush Soni, Sasha Voloshina

Wednesday, September 30, 2009

Lab 2: Theramin

Checkout the Video of "Mary Had a Little Lamb" on our electric instrument programmed on an Arduino MEGA board.


We have a small pressure pad that acts as a volume pedal, and we can select predefined tones from the knob (potentiometer). The tones were defined as the one octave scale in the natural key of C (see code below). The potentiometer sensor produces an analog input to our Arduino board, and the Arduino board was programmed to produce a digital output corresponding to the frequency of the note. The volume pedal is in series with the speaker.

We noticed the pedal was a create user-interface. It provided smooth, continuous feedback and was very easy to operate. Although we didn't get around to it, it could make a good controller for pitch due to it's continuous response to force (although sustaining extreme notes requiring high force input may be uncomfortable).

Here's a schematic of our instrument:


Here's the code we programmed into the Arduino, based on Arduino's Melody example:
/* Melody
* (cleft) 2005 D. Cuartielles for K3
* Modified by Andrew Rohr, Anish Joshi, Michael Woon
*
* This example uses a piezo speaker to play melodies. It sends
* a square wave of the appropriate frequency to the piezo, generating
* the corresponding tone.
*
* The calculation of the tones is made following the mathematical
* operation:
*
* timeHigh = period / 2 = 1 / (2 * toneFrequency)
*
* where the different tones are described as in the table:
*
* note frequency period timeHigh
* c 261 Hz 3830 1915
* d 294 Hz 3400 1700
* e 329 Hz 3038 1519
* f 349 Hz 2864 1432
* g 392 Hz 2550 1275
* a 440 Hz 2272 1136
* b 493 Hz 2028 1014
* C 523 Hz 1912 956
*
* http://www.arduino.cc/en/Tutorial/Melody
*/

#include

int tone=0;
int addr = 0;
int speakerPin = 9;
int ledPin = 13;
int sensorPin = 0; //Analog Input ~0-5V
float sensorValue = 0;
char n = 'c';
char n1='c';

int length = 15; // the number of notes
float prevval=0;
float val=0;
int j=2;

void setup() {
pinMode(speakerPin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(sensorPin, INPUT);
}

void loop() {


sensorValue = analogRead(sensorPin)/100;

if(prevval!=sensorValue)
{
EEPROM.write(addr,sensorValue);
addr=addr+1;
}


if(addr == 512)
addr=0;

if (sensorValue <= 1){ n1 = 'c'; digitalWrite(ledPin,HIGH); //playNote(n); } if (sensorValue > 1 && sensorValue <= 2){ digitalWrite(ledPin,LOW); n1 = 'd'; //playNote(n); } if (sensorValue > 2 && sensorValue <= 3){ n1 = 'e'; digitalWrite(ledPin,HIGH); //playNote(n); } if (sensorValue > 3 && sensorValue <= 4){ n1 = 'f'; digitalWrite(ledPin,LOW); //playNote(n); } if (sensorValue > 4 && sensorValue <= 5){ n1 = 'g'; digitalWrite(ledPin,HIGH); // playNote(n); } if (sensorValue > 5 && sensorValue <= 6){ n1 = 'a'; digitalWrite(ledPin,LOW); // playNote(n); } if (sensorValue > 6 && sensorValue <= 7){ n1 = 'b'; digitalWrite(ledPin,HIGH); //playNote(n); } if (sensorValue > 7 && sensorValue <= 8){ n1 = 'C'; digitalWrite(ledPin,LOW); //playNote(n); } char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' }; int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 }; n=n1; // play the tone corresponding to the note name for (int i = 0; i < tone="tones[i];" j="2;">0)
{
int sensor = 0;
sensor=analogRead(sensorPin);
if(sensorValue!=sensor)
j=-1;
digitalWrite(speakerPin, HIGH);
delayMicroseconds(tone);
digitalWrite(speakerPin, LOW);
delayMicroseconds(tone);

}

}

}

n1 ='d';
prevval=sensorValue;
}

n1 ='d';
prevval=sensorValue;
}