Basics: Senior at MIT
Courses: 6-2 (Electrical Engineering and Computer Science) and 18 (Mathematics)
Primary interests: Autonomous and interactive Robotics
Two projects: Human-climbing robot and keyboard pants.
I've always wanted a pet robot that could sit on my shoulder or walk around if I put him down on the floor. It's a project that I have sketches for going back to senior year of high school (but unfortunately not ones that I have available to take pictures of). The biggest challenge that's stopped me from making one of these so far is I still am trying to figure out a good way to make legs -- I want them to be clingy and able to hold on to a shoulder, but without hurting.
Making lizards and knex with a laser cutter!
Milling a PCB, soldering it, plus some website making adventures.
Android gear necklace, 3D scanning Pooh and a friend, 3D printing the scanned Pooh.
I wanted to design something small, cute, and with internal parts that moved. I decided on making a steampunk-esque necklace in the shape of a Google Android with internal gears. The final model had 7 independent gears, each sized differently. I designed the outer case first, making the shape of the android, with insets for eyes. I also added appropriately sized shafts for each of the gears. This made the main body for the necklace.
Next, I made each of the gears. Each of the gears was very similar, so I just copied the model and made slight edits to the values of the original sketch. Most of the gears I built in 3 pieces: the first original circle, the outside gears (made with a circular pattern in the sketch) and finally a hole in the center. Two of the larger gears also had holes so that we could see through them to the gears beneath them. They were a separate sketchthat was repeated with a circular pattern.
I learned how to put holes in a curved surface in Solidworks this week. You have to first create a plane perpendicular to the surface you want to cut through, then make the cut extend through the curved surface. I used this to make the two holes at the top where the necklace cord will go through.
Final printed model.
The final model didn't come out as well as I'd like. Unfortunately, I didn't get the piece back until after the second 3D printing run had happened, but I'm planning to revise the model to rerun next week. One of the gears had accidentally been placed too low, so it merged with other parts and wasn't free to spin. Beyond that, it turns out that I'd left too much space around the shafts -- a 1mm margin left far too much slop. I'm planning to reduce that distance to .3 or .4 mm on either side -- just slightly above the precision of the 3D printer. Also, one shaft was too narrow, and broke off before I even saw the piece. Some of the gears were also made slightly too small and were too far apart from each other to mesh well, even without the slop. I need to increase the size of these gears, and decrease the size of the one gear that was too close to the edge and was attached to the edge. This is the final model after I tried to disconnect the gears where they'd been improperly attached.
Scanning was incredibly finicky. It took numerous tries to figure out the right distance and settings with which to scan an object. About 3 feet away worked the best. The pictures below show 2 failed scans, followed by a working raw scan and then the cleaned up version of the working raw scan. I couldn't manage to get a scan 100% of the way around the model, but I did get the front half -- enough to get a scan that was obviously recognizable as Pooh.
I spent a while cleaning up the back of the model to make it as flat as possible, then I 3D printed it on the Up printer. It didn't come out quite as well as I'd hoped -- the colors on the scan definitely helped it look more like Pooh. The super small size I decided to print it at didn't help either. But it still came out pretty well!
The software worked a lot better at scanning a head. I still wound up losing tracking partway through, but I got a lot farther before losing it and the scan didn't wind up making any obvious mistakes. I didn't actually want a 3D printed model of my friend's head, so I didn't bother to repeat the scan or clean it up in order to print.
Learning to use a large format CNC, making a laptop stand.
Designing an updated hello world board, plus fabricating it.
Chocolates and a soft robotic hand.
Debugging serial communication + blinky lights.
Composite sled!
Flex and force sensors on a soft robotic hand.
Servo for turning off an electric blanket.
Revised servo board to be controlled via bluetooth. (Not in class for Thanksgiving today).
Some GUI edits and ROS integration.
#include#include #define output(directions,pin) (directions |= pin) // set port direction for output #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define pin_test(pins,pin) (pins & pin) // test for port pin #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define bit_delay_time 102 // bit delay for 9600 with overhead #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay #define char_delay() _delay_ms(10) // char delay #define serial_port PORTB #define serial_direction DDRB #define serial_pin_out (1 << PB2) void put_char(volatile unsigned char *port, unsigned char pin, char txchar) { // // send character in txchar on port pin // assumes line driver (inverts bits) // // start bit // clear(*port,pin); bit_delay(); // // unrolled loop to write data bits // if bit_test(txchar,0) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,1) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,2) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,3) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,4) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,5) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,6) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,7) set(*port,pin); else clear(*port,pin); bit_delay(); // // stop bit // set(*port,pin); bit_delay(); // // char delay // bit_delay(); } int main(void) { // // main // static char chr; // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // initialize output pins // set(serial_port, serial_pin_out); output(serial_direction, serial_pin_out); // // init A/D // ADMUX = (0 << REFS2) | (0 << REFS1) | (0 << REFS0) // Vcc ref | (0 << ADLAR) // right adjust | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0); // ADC3 1 0 for ADC4, 1 1 for ADC3 ADCSRA = (1 << ADEN) // enable | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128 // // main loop // while (1) { // // send framing // put_char(&serial_port, serial_pin_out, 1); char_delay(); put_char(&serial_port, serial_pin_out, 2); char_delay(); put_char(&serial_port, serial_pin_out, 3); char_delay(); put_char(&serial_port, serial_pin_out, 4); char_delay(); ADMUX = (0 << REFS2) | (0 << REFS1) | (0 << REFS0) // Vcc ref | (0 << ADLAR) // right adjust | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0); // ADC3 1 0 for ADC4, 1 1 for ADC3 // // initiate conversion // ADCSRA |= (1 << ADSC); // // wait for completion // while (ADCSRA & (1 << ADSC)) ; // // send result // chr = ADCL; put_char(&serial_port, serial_pin_out, chr); char_delay(); chr = ADCH; put_char(&serial_port, serial_pin_out, chr); char_delay(); ADMUX = (0 << REFS2) | (0 << REFS1) | (0 << REFS0) // Vcc ref | (0 << ADLAR) // right adjust | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (0 << MUX0); // ADC4 1 0 for ADC4, 1 1 for ADC3 // // initiate conversion // ADCSRA |= (1 << ADSC); // // wait for completion // while (ADCSRA & (1 << ADSC)) ; // // send result // chr = ADCL; put_char(&serial_port, serial_pin_out, chr); char_delay(); chr = ADCH; put_char(&serial_port, serial_pin_out, chr); char_delay(); } }
from Tkinter import * import serial WINDOW = 600 # window size eps1 = 0.5 # filter time constant filter1 = 0.0 # filtered value eps2 = .5 filter2 = 0 def idle(parent,canvas): global filter1, eps1 global filter2, eps2 # # idle routine # byte2 = 0 byte3 = 0 byte4 = 0 ser.flush() while 1: # # find framing # byte1 = byte2 byte2 = byte3 byte3 = byte4 byte4 = ord(ser.read()) if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)): break low = ord(ser.read()) high = ord(ser.read()) value1 = 256*high + low filter1 = (1-eps1)*filter1 + eps1*value1 x = int(.2*WINDOW + (.9-.2)*WINDOW*filter1/1024.0) low = ord(ser.read()) high = ord(ser.read()) value2 = 256*high + low filter2 = (1-eps2)*filter2 + eps2*value2 y = int(.2*WINDOW + (.9-.2)*WINDOW*filter2/1024.0) canvas.itemconfigure("text1",text="%.1f"%filter1) canvas.coords('rect1',.2*WINDOW,.05*WINDOW,x,.2*WINDOW) canvas.coords('rect2',x,.05*WINDOW,.9*WINDOW,.2*WINDOW) canvas.itemconfigure("text2",text="%.1f"%filter2) canvas.coords('rect3',.2*WINDOW,.3*WINDOW,y,.45*WINDOW) canvas.coords('rect4',y,.3*WINDOW,.9*WINDOW,.45*WINDOW) canvas.update() parent.after_idle(idle,parent,canvas) # # check command line arguments # if (len(sys.argv) != 2): print "usage: command line: python term.py serial_port" sys.exit() port = sys.argv[1] # # open serial port # ser = serial.Serial(port,9600) ser.setDTR() # # set up GUI # root = Tk() root.title('term.py (q to exit)') root.bind('q','exit') canvas = Canvas(root, width=WINDOW, height=.6*WINDOW, background='white') canvas.create_text(.1*WINDOW,.125*WINDOW,text=".33",font=("Helvetica", 24),tags="text1",fill="#0000b0") canvas.create_rectangle(.2*WINDOW,.05*WINDOW,.3*WINDOW,.2*WINDOW, tags='rect1', fill='#b00000') canvas.create_rectangle(.3*WINDOW,.05*WINDOW,.9*WINDOW,.2*WINDOW, tags='rect2', fill='#0000b0') canvas.create_text(.1*WINDOW,(.5-.125)*WINDOW,text=".33",font=("Helvetica", 24),tags="text2",fill="#0000b0") canvas.create_rectangle(.2*WINDOW,.3*WINDOW,.3*WINDOW, .45*WINDOW, tags='rect3', fill='#b00000') canvas.create_rectangle(.3*WINDOW,.3*WINDOW,.9*WINDOW,.45*WINDOW, tags='rect4', fill='#0000b0') canvas.pack() # # start idle loop # root.after(100,idle,root,canvas) root.mainloop()
#!/usr/bin/env python # license removed for brevity import rospy from std_msgs.msg import String from test_code.msg import SerialMsg import serial eps1 = 0.5 # filter time constant filter1 = 0.0 # filtered value def go_publish(): ser = serial.Serial('/dev/ttyUSB0', 9600) ser.setDTR() pub = rospy.Publisher('flex_sensor_vals', SerialMsg) rospy.init_node('serial_publisher_py', anonymous=True) r = rospy.Rate(10) # 10hz while not rospy.is_shutdown(): global filter1, eps1 global filter2, eps2 # # idle routine # byte2 = 0 byte3 = 0 byte4 = 0 ser.flush() while 1: # # find framing # byte1 = byte2 byte2 = byte3 byte3 = byte4 byte4 = ord(ser.read()) if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)): break low = ord(ser.read()) high = ord(ser.read()) value1 = 256*high + low filter1 = (1-eps1)*filter1 + eps1*value1 msg = SerialMsg() msg.type = 1 msg.value = filter1 rospy.loginfo("got filter value!") pub.publish(msg) r.sleep() if __name__ == '__main__': try: go_publish() except rospy.ROSInterruptException: pass
West section made a painting machine!
A large cardboard spaceship with LED constellations.