loading

Step 9: Pitchbend and Arduino

Now that you know how to control note on and note off, you can try pitchbend.

Pitchbend information is stored in 2 data bytes, and most significant byte (MSB) and a least significant byte (LSB). Each of these bytes contains only 7 bits of information. This means that all pitchbend information is stored in 14 bits, with the most significant 7 bits stored in the MSB and the least significant 7 bits stored in the LSB.

For most applications you will only find yourself changing pitchbend via the MSB and just setting the LSB to 0. In this case you have 7 bits of resolution for pitchbend (128 steps). In MIDI protocol pitchbend = 64 is no pitchbend, pitchbend greater than 64 is pitchbends the frequency up, and less than 64 pitchbends the frequency down.

In the example below a note played and held, then played again while the pitchbend increments from 64 to its max value of 127, then played a third time while the pitchbend increments from 64 to its min value of 0. This sequence is looped forever. The images above show the output in ableton from this Arduino sketch.

<pre>/*
MIDI Pitchbend (msb)
By Amanda Ghassaei
July 2012
http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/

 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.

*/
 

 
 int noteON = 144;//144 = 10010000 in binary, note on command
 //noteON data storage:
 int note = 60;//middle c
 int velocity = 100;//velocity of MIDI notes, must be between 0 and 127
 //(higher velocity usually makes MIDI instruments louder)
 
 int pitchbend = 224;//224 = 11100000 in binary, pitchbend command
 //pitchbend data storage:
 int lsb = 0;//least siginificant bit of pitchbend message
 int msb = 0;//most significant bit of pitchbend message

void setup() {
  //  Set MIDI baud rate:
  Serial.begin(31250);
}

void loop() {
  //first play note w/o pitchbend
  MIDImessage(pitchbend, 0, 64);//reset pitchbend to 0 (zero pitchbend is lsb = 0, msb = 64)
  MIDImessage(noteON, note, velocity);//turn note on
  delay(700);//sustain note
  MIDImessage(noteON, note, 0);//turn note off
  delay(500);//wait 500ms until triggering next note
  
  //then play with pitchbend up
  MIDImessage(pitchbend, 0, 64);//reset pitchbend to 0 (zero pitchbend is lsb = 0, msb = 64)
  MIDImessage(noteON, note, velocity);//turn note on
  for (msb=64;msb<=127;msb++){//increase pitchbend  msb 64 (no pitchbend) to 127
    MIDImessage(pitchbend, lsb, msb);//send pitchbend message
    delay(10);
  }
  MIDImessage(noteON, note, 0);//turn note off
  delay(500);//wait 500ms until triggering next note
  
  //then play with pitchbend down
  MIDImessage(pitchbend, 0, 64);//reset pitchbend to 0 (zero pitchbend is lsb = 0, msb = 64)
  MIDImessage(noteON, note, velocity);//turn note on
  for (msb=64;msb>=0;msb--){//decrease pitchbend msb from 64 (no pitchbend) to 0;
    MIDImessage(pitchbend, lsb, msb);//send pitchbend message
    delay(10);
  }
  MIDImessage(noteON, note, 0);//turn note off
  delay(500);//wait 200ms until triggering next note
}

//send MIDI message
void MIDImessage(int command, int data1, int data2) {
  Serial.write(command);//send command byte
  Serial.write(data1);//send data byte #1
  Serial.write(data2);//send data byte #2
}


Below is a video demonstration of the code above. For this piece of code, pitchbend will be most noticeable in instruments with a long sustain, such as a string instrument, keep that in mind when testing the code for yourself.

You will most likely be fine using only 128 steps of pitchbend resolution, but in case you must use all 16384 steps, see the code below. Basically what I've done here is defined a variable called pitchbendVal, which varies from 0 to 16383. As I said below the "zero" pitchbend value is msb = 64 and lsb = 0. In binary this is:

MSB = 64 = 01000000
LSB = 0 = 0000000

(remember MSB and LSB are 7 bit numbers)

putting these values together we get:

1000000 0000000
MSB LSB

or

10000000000000
which translates to 8192 in decimal

so now the "zero" pitchbend value is 8192.

You'll also notice I had to break the variable pitchbendVal into two 7 bit parts to send out via MIDI message:
MIDImessage(pitchbend, (pitchbendVal&127), (pitchbendVal>>7));
the first part, pitchbendVal&127, returns the least significant 7 bits of pitchbendVal
the second part, pitchbendVal>>7, returns the most significant 7 bits of pitchbendVal
see & and >> on the Arduino reference page for more info.
<pre>/*
MIDI Pitchbend (full resolution)
By Amanda Ghassaei
July 2012
http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/

 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.

*/
 

 
 int noteON = 144;//144 = 10010000 in binary, note on command
 //noteON data storage:
 int note = 60;//middle c
 int velocity = 100;//velocity of MIDI notes, must be between 0 and 127
 //(higher velocity usually makes MIDI instruments louder)
 
 int pitchbend = 224;//224 = 11100000 in binary, pitchbend command
 //pitchbend data storage:
 int pitchbendVal = 8192;//value between 0 and 16383. zero pitchbend = 8192

void setup() {
  //  Set MIDI baud rate:
  Serial.begin(31250);
}

void loop() {
  //first play note w/o pitchbend
  pitchbendVal = 8192;//reset pitchbend to "0" (zero pitchbend is pitchbendVal = 8192)
  MIDImessage(pitchbend, (pitchbendVal&127), (pitchbendVal>>7));//send pitchbend message
  MIDImessage(noteON, note, velocity);//turn note on
  delay(700);//sustain note
  MIDImessage(noteON, note, 0);//turn note off
  delay(500);//wait 500ms until triggering next note
  
  //then play with pitchbend up
  pitchbendVal = 8192;//reset pitchbend to "0" (zero pitchbend is pitchbendVal = 8192)
  MIDImessage(pitchbend, (pitchbendVal&127), (pitchbendVal>>7));//send pitchbend message
  MIDImessage(noteON, note, velocity);//turn note on
  for (pitchbendVal=8192;pitchbendVal<16384;pitchbendVal++){//increase pitchbend from 8192 to 16383
    MIDImessage(pitchbend, (pitchbendVal&127), (pitchbendVal>>7));//send pitchbend message
    delay(1);
  }
  MIDImessage(noteON, note, 0);//turn note off
  delay(500);//wait 500ms until triggering next note
  
  //then play with pitchbend down
  pitchbendVal = 8192;//reset pitchbend to "0" (zero pitchbend is pitchbendVal = 8192)
  MIDImessage(pitchbend, (pitchbendVal&127), (pitchbendVal>>7));//send pitchbend message
  MIDImessage(noteON, note, velocity);//turn note on
  for (pitchbendVal=8192;pitchbendVal>=0;pitchbendVal--){//decrease pitchbend 8192 to 0;
    MIDImessage(pitchbend, (pitchbendVal&127), (pitchbendVal>>7));//send pitchbend message
    delay(1);
  }
  MIDImessage(noteON, note, 0);//turn note off
  delay(500);//wait 500ms until triggering next note
}

//send MIDI message
void MIDImessage(int command, int data1, int data2) {
  Serial.write(command);//send command byte
  Serial.write(data1);//send data byte #1
  Serial.write(data2);//send data byte #2
}

<p>Hello<br><br>I'm trying to do a laser harp using midi. But I always sound ! Could someone help me find the error in the code? Thanks</p>
<p>Hi,<br>I have made a harp like you... send me message to talk...</p>
<p>Hello,</p><p>I'm trying to receive MIDI notes from an Axiom 49 keyboard using your tutorial and exact resistor values, but nothing comes out when i try the middle C (only &quot;-1&quot;).<br><br></p>
<p>Only difference is the baud rate that i tried to set to 19200, 38400, 57600 instead of 31250.</p>
<p>Hello<br><br>I'm trying to do a laser harp using midi. But I always sound ! Could someone help me find the error in the code? Thanks</p>
<p>Hello<br><br>I'm trying to do a laser harp using midi. But I always sound ! Could someone help me find the error in the code? Thanks</p>
<p>Hi im trying to receive midi to control solenoids, so ive it set up exactly as its shown but when i play a file the led wont blink, im using cubase to play the files. Im just wondering if theres some sort of setup im mssing? Thanks</p>
Why do the other tutorials use optocouplers and you don't? Can I use this with a drum machine
I do use an optocoupler to receive MIDI. This will work with anything that sends or receives MIDI.
<p>Ah! Thank you so much for the response, didn't see the last part. Can note on and note off be used as clock signals as well to send to drum machines etc?</p>
Or is it computer only *
<p>Hello Amanda! Thank you for the tutorial!! I have a question about step 10. Everything works great. I can turn the LED on with a midi note. But what if I want to turn it off with the same note? And what if I want to do it permanently but not once. I mean how can I make some kind of switch out of that note? What should I add to the code or how it should be transformed? Thank you! </p>
<p>What software are you using to send the MIDI?</p>
<p>Hi! I use Cubase.</p>
<p>Hello! Im very interested in this tutorial. I want to receive MIDI with the Arduino, but you don't say anything about how to send it from the Computer. Do you know any Software that can send MIDI songs to the Arduino? I'm really having a headache with this point.</p><p>Thanks!</p>
<p>Hi, thank you for this instructable. You 're talking in step 10 about using timers of the arduino if we care about timing. Would it be a good solution to use external interrupt?</p><p>Thanks again.</p>
<p>Hi, great Instructable thank you. Has anyone done anywork on reading USB class compliant devices as these are quite predominant in the market. I was interested in terms of Midi note remapping. I can do this easily in Max but it would be great to have a standalone USB device. Thanks</p>
<p>Hello again! I changed your code a bit to turn one LED on/off with the exact midi notes. Everything works except one thing the led sometimes doesn't want to go off. And besides nothing works without the &quot;delay&quot; in the loop. I'm an arduino beginner. If you please could you say what I did wrong? Thank you! </p><p>byte commandByte;</p><p>byte noteByte;</p><p>byte velocityByte;</p><p>byte noteOn = 10010000;</p><p>void setup(){</p><p> Serial.begin(115200);</p><p> pinMode(12,OUTPUT);</p><p> }</p><p>void checkMIDI(){</p><p> if (Serial.available()){</p><p> commandByte = Serial.read();</p><p> noteByte = Serial.read();</p><p> velocityByte = Serial.read();</p><p> if (commandByte == noteOn){</p><p> if (noteByte == 95 &amp;&amp; velocityByte &gt; 0){</p><p> digitalWrite(12,HIGH);//turn on led</p><p>}</p><p>}</p><p> if (commandByte == noteOn){</p><p> if (noteByte == 93 &amp;&amp; velocityByte &gt; 0){</p><p> digitalWrite(12,LOW);</p><p>} </p><p>}</p><p>}</p><p>} </p><p>void loop()</p><p>{</p><p> checkMIDI();</p><p> delay(1);</p><p>}</p>
<p>Hi, great tutorial! I've been making midi controllers for a while, but just with midi out, now I want to have som feedback from the software. I've made a controllers with a couple encoders and what I want to do is to update the cc value of the encoders when I play in the knobs in the software. any clue on how to do? Thanks!</p>
<p>Thanks for the great 'ible.</p><p><iframe allowfullscreen="" frameborder="0" height="281" src="//www.youtube.com/embed/wUUEu4H2_tE" width="500"></iframe></p><p>Do you know how to do something like this. I basically want to be able to read midi files from the Arduino and connect it to a MIDI device. I'm planning (if this is possible!) to have LEDs which light up when a specific note is played - it could also display the MIDI velocity by changing its brightness with PWM.</p>
<p>Hi there,</p><p>Have a look at this device you can get for 91 euros : the Midilektor.</p><p><a href="http://www.orgautomatech.com/epages/3b85d6ba-28b0-11e2-b53b-000d609a287c.sf/en_GB/?ObjectPath=/Shops/3b85d6ba-28b0-11e2-b53b-000d609a287c/Products/Midilec" rel="nofollow">http://www.orgautomatech.com/epages/3b85d6ba-28b0-...</a></p><p>I've bought is 5 years ago, and , combined with a midi decoder from the same provider, it works perfectly on a street organ .</p><p>Jean-Paul </p>
<p>congratulations for detailed instructable I could make my MIDI OUT and MIDI IN connections thanks to the tutorial, the MIDI OUT connection could first since the MIDI IN messed up enough, first mistake was to connect the MIDI input to the contrary (pin 2 to pin 4 and pin 4 on pin 2), the second was the diode, called the entrance 4 6N139 to inves entry 3, the third and final error was carrying coding in arduino with zero connected pin, gave several errors ... Finally I watched one toturial to set the MIDI OUT on the fruit loops and is now running smoothly ... once again, thank you! I am Brazilian and I'm using google translator, sorry for the grammatical errors ...</p>
<p>The &quot;Receive MIDI Messages&quot; diagram is incorrect, and does not match the picture of the board. The MIDI jack wires should go to the opposite IC pins as shown in the diagram. Took me a while to figure this out.</p>
<div>when I try to use the MIDI Hairless and try to connect with the port of arduino, the error &quot;this application has Requested the Runtime to terminate it in an unusual way&quot; shows how I can fix this?</div>
<p>Hi, I realize this is an old thread, but I am having the same issue. How did you resolve it?</p>
<p>Hi Amanda,</p><p>Great Tutorial. However when it comes to Electronics my knowledge is limited at best. I was wondering whether you would mind further explaining the use of the optocoupler for receiving data... If I could understand WHY we use it the rest will become clearer to me. Many Thanks. Chris</p>
<p>hey, sorry for the late reply. <a target="_blank" href="http://www.midi.org/techspecs/electrispec.phphttps://en.wikipedia.org/wiki/Opto-isolator">Optocouplers</a> isolate circuits from each other by using light to transmit data instead of voltage. This can be useful if two circuits need to communicate with each other and they use different voltages to transmit data signals (eg 5V vs 3.3V logic). In this case it's not a voltage difference, I think the optocoupler is there to protect from current spikes. It is required in the <a target="_blank" href="http://www.midi.org/techspecs/electrispec.phphttps://en.wikipedia.org/wiki/Opto-isolator">specs</a>.</p>
The optocoupler provides electrical insulation between equipments. This avoids several problems that plague audio devices, like ground loops and hum pickup.
<p>Hi Amanda!</p><p>I think your phrase: </p><p>&quot;The last half of the command byte sets the MIDI channel. All the bytes <br>listed above would be in channel 0, command bytes ending in 0001 would <br>be for MIDI channel 1, and so on.&quot;</p><p>is not exact, because in 4 bits values go from 0 to 15. So a byte ending 0001 means 2. </p>
<p>Hi your tutorial is very usefull :-)</p><p>I just have a probleme. I tried you receive and check midi if note = 60 and it work. So i decided to modify it to light up 8 led when i play on my midi keyboard. So i made this programme but it does'nt work. </p><p>/*<br>By Amanda Ghassaei<br>July 2012<br><a href="http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/" rel="nofollow">http://www.instructables.com/id/Send-and-Receive-M...</a><br><br><br>*/<br><br>byte commandByte;<br>byte noteByte;<br>byte velocityByte;<br><br>byte noteOn = 144;<br><br><br>void setup(){<br> <br> Serial.begin(56000);<br> pinMode(13,OUTPUT);<br> pinMode(12,OUTPUT);<br> pinMode(11,OUTPUT);<br> <br> digitalWrite(13,LOW);<br> digitalWrite(12,LOW);<br> digitalWrite(11,LOW);<br> <br>}<br><br>void directblink13(){<br> digitalWrite(13,HIGH);//turn on led<br> delay(1000);<br> digitalWrite(13,LOW);<br> }<br>void directblink12(){<br> digitalWrite(12,HIGH);//turn on led<br> delay(1000);<br> digitalWrite(12,LOW);<br> }<br>void directblink11(){ <br> digitalWrite(11,HIGH);<br> delay(1000);<br> digitalWrite(11,LOW); <br> }<br><br>void checkMIDI(){<br> do{<br> if (Serial.available()){<br> commandByte = Serial.read();//read first byte<br> noteByte = Serial.read();//read next byte<br> velocityByte = Serial.read();//read final byte<br> if (commandByte == noteOn){//if note on message<br> //check if note == 60 and velocity &gt; 0<br> if (noteByte == 60 &amp;&amp; velocityByte &gt; 0){directblink13;}<br> <br> else if(noteByte == 61 &amp;&amp; velocityByte &gt; 0){directblink12;}<br> <br> else if(noteByte == 62 &amp;&amp; velocityByte &gt; 0){ directblink12;}<br> }<br> <br> <br> <br> }<br> <br> }<br> while (Serial.available() &gt; 2);//when at least three bytes available<br>}<br> <br><br>void loop(){<br> checkMIDI();<br> delay(1);<br><br>}</p><p>Thanks :-)</p>
<p>When you're calling your directblink functions, you're forgetting to add ()</p><p>So a call should be: directblink12();</p>
<p>Hey Amanda. I've written some very simple code that receives MIDI and turns on some LEDs via the pwm. I'm receiving the messages via Hairless so no need for the external MIDI wirings.</p><p>For some reason the program will only work when there is a short delay of minimum 4ms after the checkMIDI() function is called. If there is no delay, the LEDs dont light up. The only problem is, this causes some messages to be missed. Any idea why? </p><p>Below is the code:</p><p>byte commandByte;</p><p>byte secondByte;</p><p>byte thirdByte;</p><p>byte noteOn = 144;</p><p>byte noteOff = 128;</p><p>byte pitchBend = 224;</p><p>int pwmVal;</p><p>void setup()</p><p>{</p><p> Serial.begin(9600);</p><p> pinMode(3,OUTPUT);</p><p>}</p><p>void checkMIDI()</p><p>{</p><p> do</p><p> {</p><p> if (Serial.available())</p><p> {</p><p> commandByte = Serial.read();//read command byte</p><p> secondByte = Serial.read();//read next byte (MSB, or Note)</p><p> thirdByte = Serial.read();//read final byte (LSB or velocity)</p><p> if (commandByte == noteOn)</p><p> {</p><p> if (secondByte &gt; 0 &amp;&amp; thirdByte &gt; 0)</p><p> {</p><p> pwmVal = map(thirdByte,0,127,0,255);</p><p> analogWrite(3,pwmVal);//turn on led with velocity value</p><p> }</p><p> }</p><p> else if(commandByte == noteOff)</p><p> {</p><p> analogWrite(3,0);</p><p> }</p><p> }</p><p> }</p><p> while (Serial.available() &gt; 2);//when at least three bytes available</p><p>}</p><p>void loop()</p><p>{</p><p> checkMIDI();</p><p> delay(4);</p><p>}</p>
<p>Sorry, I conducted as your instructable and I found that midiout message can be received normally by hairless software. But it seemed that the midiin.maxpat didn't work as what presented in your video.</p><p>I am trying to figure out this problem. I am assuming that the problem occurs when hairless route message to MAX, but I don't know where goes wrong.</p>
<p>maybe try selecting another midi channel in hairless midi/max. There might be something called From/To MaxMSP</p>
<p>Hi Amanda, thanks for your extensive tutorial! I'm thinking of building a touch capacitative midi keyboard and am trying to figure out how to translate the amount of touch recieved to velocity of note. So &lt; touch &lt; volume. Just wondering if you could help me out. Thanks!</p>
<p>No problem. Read in touch data from an analog pin (number between 0-1023) then scale that number down to a number between 0-127 using the <a target="_blank" href="https://www.arduino.cc/en/reference/map">map</a> function. Then send that out as the velocity. You can start with the variable velocity code I wrote and modify it to use the touch velocity from your sensor.</p>
<p>Hey There!</p><p>I am currently working on this project and everything is working fine so far. Is there a big difference between an 6N138 and an 6N137 Optocoupler? Am I able to build Step10 with an 6N137 Optocoupler too? </p><p>By the way: <strong>Awesome </strong>tutorial!!!</p><p>Greetings from Germany ;)</p>
<p>I'm not sure. If the pin outs are the same and the basic specs (input/output voltage/current, etc) look the same and are withing range for the arduino it's worth it to try. Did you try it already?</p>
<p>Thank you for this great tutorial! I've tried the midi out and works perfectly, I even managed to have arduino play poliphony in my synth. I haven't tried the midi in because I don't have the octocoupler yet but in the meanwhile I've been having a look at the schematics and the photos and there's something I don't understand (I'm a just a beginner in arduino/electronics): in the schematics, the cable with the 220ohm resistor comes out from the octocoupler's pin 2, but in the photos the resistor is soldered to the yellow cable, which in turn comes from pin 3.</p><p>Should I solder the resistor to the yellow or the green cable? To which pins in the octocoupler should the yellow and green cable ba connected?</p><p>Many thanks! :-)</p>
<p>hey, I see where the confusion is coming from, but it's been so long I'm not sure. I would probably go with the schematic, did you find out which pin was correct?</p>
<p>Hi!<br>First of all, thank you for this great instructable!<br>I'm currently using MIDI as input on my Arduino Uno and use Arduino as output translator device. So basically I'm playing notes on Synthesizer, send them to Arduino using MIDI, and then play them using notes library. I'm also displaying notes, velocity and event on LCD, just to se what is going on there. <br>The main problem is that the whole thing is too slow. I don't know if this happens to you, but Arduino sometimes skips or doesn't even receive the note or any MIDI message if it is played too fast. For example, if I play a note and release it emediately, the Arduino receives the first message with velocity&gt;0, but misses the second message with velocity=0. <br>I tried to make it faster by removing notes or LCD library, but it was the same. Maybe the Serial is to slow in Arduino because it is Arduino softare? Any ideas?</p>
<p>Thank you for the elaborate tutorial.</p><p>But you didn't mention how to interface the midi software like garageband when the midi messages were sent out.</p><p>I know that hairless can help messages route to garageband, but I wonder how garageband behave when receiving the Noteon command? </p>
<p>Our project is slightly different, since we do MIDI over USB and then use Hairless and LoopMIDI to interface with Ableton, but if people are interested, the code is available here:</p><p><a href="http://stephane.thunus.org/SAE/arduino.htm" rel="nofollow">http://stephane.thunus.org/SAE/arduino.htm</a></p><p>It is not 100% finished and clean, but it works - sorry, the code is a further version than the video explanations - will be updated when the project is finished.</p>
Now I did, sorry. I just got in the optocouplers from mouser, and was about to put this all together, and remembered by board in 3.3V. If I supply the optocouplers with 3.3 will I run into any obvious issues?
if you supply the optocouplers with 3.3V, then the max signal coming out of them will be 3.3V. Since you are trying to read with with one of the Arduino's digital pins, I'm concerned it might not be enough to switch it to a "HIGH" state. no harm in trying though.
<p>Hello amanda I was looking at this programs you put in here, very interesting, and thanks for sharing them a lot of things i&acute;ve learn. I have a small question is their for example any free software for arduino that can receive the midi file (for example a midi version of beethovens 5th symphony intro) and just read the notes as they came from the midi file and then to the arduino board keeping the same duration &quot;as the intro of the symphony is&quot;. For example if I want to export each note from the midi and let several leds to play each single note.<br>Thanks a lot again for sharing this. Hope you have a great day</p>
<p>You could use fl studio demo it will let you export into an audio file (mp3, wav, etc...) but not save.</p>
<p>This Code below here from you doesn't work to me.<br>The Serial.read() only put values in commandByte, but not noteByte and velocityByte? I can be sure that commandByte is always bigger than 127 and the other values 0-127 can be noteByte or velocityByte?</p><p>ISR(TIMER2_COMPA_vect) {//checks for incoming midi every 128us<br> do{<br> if (Serial.available()){<br> commandByte = Serial.read();//read first byte<br> noteByte = Serial.read();//read next byte<br> velocityByte = Serial.read();//read final byte<br> }<br> }<br> while (Serial.available() &gt; 2);//when at least three bytes available<br>}</p>
Yes the command byte is always >127 and the note and velocity (or whatever other parameters come after the command are <= 127. This code can be really finicky depending on your setup. Try removing the > 2 in the code able and see if it helps. You might want to add some additional logic to be sure that the command byte is set correctly (check if it is > 127)<br />
<p>First of all, many thanks for this awesome tutorial! It really helped me a lot. </p><p>Unfortunately, I'm having the same problem. Removing &gt;2 doesn't seem to help. With additional logic, I've discovered that noteByte reads 255, no matter wich note I play.The commandByte, noteOn and noteOff are working fine.</p>

About This Instructable

439,657views

446favorites

License:

Bio: I'm a grad student at the Center for Bits and Atoms at MIT Media Lab. Before that I worked at Instructables, writing code for ... More »
More by amandaghassaei:OTCA Metapixel - Conway's Game of Life"9 Degrees of Freedom" IMUTwitter Controlled Pet Feeder
Add instructable to: