Blog
Thanks to my dear friend Anirudh, who impishly burned a hole through the back pocket of my favorite jeans, I was rendered jeans-less for a week. Well not exactly jeansless, but lets say, figuratively. But anyways, I finally got down to patching it with some leather scraps I managed to steal from our neighbours at the lab.
I've been using solidworks to layout files to use on the lasercutter. It has been quite nice with mathematical constraints and equations and stuff. But, there have been a couple of issues
Solidworks doesn't like a huge number of chained constraints
Its difficult to abstract out common features
So, I decided to give python a shot at doing this. After a little bit of searching I found the library svgwrite. It lets you create svg files programatically, quite nice! The only thing I haven't figured out completely yet is how to get corel draw to interpret the dimensions and units correctly.
The code (here), creates basic_box.svg, which can be lasercut. A caveat though is that the lines are not hairline, so I'd have to manually do that in coreldraw.
import svgwrite from svgwrite import cm, mm side = 40 num_sides = 4 num_panels = 6 thickness=0.5 length = side*num_panels + (4*thickness) num_cuts = 10 cut_width = 0.6 dwg = svgwrite.Drawing(filename='basic_box.svg', debug=True) cuts = dwg.g(id='cuts', stroke='black') scores = dwg.g(id='scores', stroke='red') dwg.add(cuts) dwg.add(scores) def basic_box(): start_x = 0 end_x = 0 top_cut = 0 bottom_cut = 0 reference_height = 2*side for i in range(num_sides): end_x = start_x + side (top_cut,bottom_cut) = addSide(dwg,start_x,end_x,i,reference_height) start_x = start_x + side lastSide(dwg,start_x,top_cut,bottom_cut,reference_height) dwg.save() def addSide(dwg,start_x,end_x,count,reference_height): """I add horizontal cuts for each side to each panel """ #Leave for thickness #All sides meet at the hinges, so we take the top hinge as the reference top_hinges = [] top_hinges_bottom = 0 top_hinges_top = reference_height for i in range(num_cuts): top_hinges_bottom = reference_height + (i*cut_width) top_hinges.append(top_hinges_bottom) top_fold = top_hinges_top - side + (thickness*count) top_cut = top_fold - side mid_hinge = top_hinges_bottom + side bottom_hinges = [] bottom_hinge_top = mid_hinge + side for i in range(num_cuts): bottom_hinge_bottom = bottom_hinge_top + (i*cut_width) bottom_hinges.append(bottom_hinge_bottom) bottom_fold = bottom_hinge_bottom + side + (count) * thickness bottom_cut = bottom_fold + side cuts_arr = [top_cut,bottom_cut] scores_arr = [top_fold,mid_hinge,bottom_fold]+top_hinges+bottom_hinges for y in cuts_arr: cuts.add(dwg.line(start=(start_x*mm,y*mm), end=(end_x*mm,y*mm))) for y in scores_arr: scores.add(dwg.line(start=(start_x*mm,y*mm), end=(end_x*mm,y*mm))) #If this is the first side, then cut otherwise score if count == 0: cuts.add(dwg.line(start=(start_x*mm,top_cut*mm), end=(start_x*mm,bottom_cut*mm))) else: scores.add(dwg.line(start=(start_x*mm,top_fold*mm), end=(start_x*mm,top_hinges_top*mm))) cuts.add(dwg.line(start=(start_x*mm,top_hinges_top*mm), end=(start_x*mm,bottom_hinge_bottom*mm))) scores.add(dwg.line(start=(start_x*mm,bottom_hinge_bottom*mm), end=(start_x*mm,bottom_fold*mm))) cuts.add(dwg.line(start=(start_x*mm,top_cut*mm), end=(start_x*mm,top_fold*mm))) cuts.add(dwg.line(start=(start_x*mm,bottom_fold*mm), end=(start_x*mm,bottom_cut*mm))) return (top_cut,bottom_cut) def lastSide(dwg,start_x,top_cut,bottom_cut,reference_height): #Add tabs tab_length = side - (thickness*num_sides) end_x = start_x + tab_length top_hinge = reference_height top_tab_bottom = top_hinge top_tab_top = top_tab_bottom - tab_length bottom_tab_top = top_hinge + side + side + (num_cuts*cut_width*2) bottom_tab_bottom = bottom_tab_top + tab_length arr = [top_tab_top,top_tab_bottom,bottom_tab_top,bottom_tab_bottom] for y in arr: cuts.add(dwg.line(start=(start_x*mm,y*mm), end=((end_x*mm,y*mm)))) cuts.add(dwg.line(start=(end_x*mm,top_tab_top*mm), end=((end_x*mm,top_tab_bottom*mm)))) cuts.add(dwg.line(start=(end_x*mm,bottom_tab_top*mm), end=((end_x*mm,bottom_tab_bottom*mm)))) scores.add(dwg.line(start=(start_x*mm,top_tab_top*mm), end=((start_x*mm,top_tab_bottom*mm)))) scores.add(dwg.line(start=(start_x*mm,bottom_tab_top*mm), end=((start_x*mm,bottom_tab_bottom*mm)))) cuts.add(dwg.line(start=(start_x*mm,top_cut*mm), end=((start_x*mm,top_tab_top*mm)))) cuts.add(dwg.line(start=(start_x*mm,bottom_cut*mm), end=((start_x*mm,bottom_tab_bottom*mm)))) cuts.add(dwg.line(start=(start_x*mm,top_tab_bottom*mm), end=((start_x*mm,bottom_tab_top*mm)))) def addLineCut(dwg,a,b): pass def addLineScore(dwg,a,b): pass if __name__ == '__main__': basic_box()
Anyways, here's what it comes out when finished.
The iMX233 has a half-duplex chipset, which means Py-Spidev doesn't work out of the box with olinuxino-micro. I've made some trivial changes to the library to enable support for half-duplex spi chipsets. Works like a charm on my olinuxino micro. Get it here: https://github.com/pragun/py-spidev.
(test)[root@olinuxino py-spidev]# python2.7 Python 2.7.3 (default, Dec 25 2012, 23:03:24) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import spidev >>> spi = spidev.SpiDev() >>> spi.open(32766,1) >>> spi.xfer([1,2,3,4],duplex=False,receive=True) [110, 111, 112, 113] >>> spi.xfer([1,2,3,4],duplex=False,receive=True) [114, 115, 116, 117] >>> spi.xfer([1,2,3,4],duplex=False,receive=True) [118, 119, 120, 121] >>> spi.xfer([1,2,3,4],duplex=False,receive=True) [122, 123, 124, 125]
My joy after making the second version of SideBox was shortlived as the first SideBox_v0.2 failed quite catastrophically. Anyways, I think the problem could be easily rectified by increasing the amount width of the border around the failing tab slot.
While I'm procrastinating about going down to the shop and making one more, duct tape seems to take care of stuff!
This post is more like a reminder for me on how I got WiFi to work on my OlinuxinoMicro, prepared in the last post. I used a Edimax EW-7811Un and it works (so go ahead and order one if you've been looking for confirmation)!. Assuming you followed the steps in the previous post, and have a linux kernel with the 8192cu module, here's how you'd go. Most of these steps should be trivial, for a linux hacker, but again a little bit of convenience doesnt hurt. Whatever I have here is a subset of and has been derived from here.
Step 1: Make sure you have the 8192cu module inserted.
modprobe 8192cu
Step 2: It doesn't hurt to check the list of network interfaces you have
ls -l /sys/class/net ifconfig iwconfig
Step 3: If your olinuxino is like mine, you might get a wlan0 in iwconfig, but only a lo in ifconfig.
[root@olinuxino ~]# iwconfig lo no wireless extensions. wlan0 unassociated Nickname:"" Mode:Auto Frequency=2.412 GHz Access Point: Not-Associated Sensitivity:0/0 Retry:off RTS thr:off Fragment thr:off Encryption key:off Power Management:off Link Quality:0 Signal level:0 Noise level:0 Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:0 Invalid misc:0 Missed beacon:0 [root@olinuxino ~]# ifconfig lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 0 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
If that is the case, the following set it up for me.
ip link set wlan0 up
[root@olinuxino ~]# ifconfig lo: flags=73mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 0 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 wlan0: flags=4099 mtu 1500 ether 80:1f:02:9b:ec:50 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Step 4: You should basically be set now. Do a,
iwlist scan
to see what you get!
Olinuxino is an open source, affordable linux board based on the FreeScale iMXX233 arm microcontroller. It sounded just perfect for my project on Kenya's power distribution (GrassRoots). I needed my olinuxino-micro to talk to an Atmega328 over SPI. Sounds trivial, but getting SPI to work on the olinuxino is pretty painful. So here's part 1 of how to get it to work (part 1 covers getting spidev_test.c to work). Oh, one more thing, this uses spidev, which is a nice user space interface to talk SPI!. Almost everything here is taken from imx23-olinuxino and here
So, here it goes.
Step 1: Get your hands on an Olimex Olinuxino (the redder the better!) and microSD card.
Step 2: Install your regular ArchLinux for olinuxino on the microSD card, I just got mine from http://archlinuxarm.org/platforms/armv5/olinuxino
Step 3: Test to see if things boot up! -Yes: Go ahead! -No: Next steps sort of depend on your success in step3
Step 4: Get your cross-compile environment working! For me, this meant
Updating apt repositories so that apt finds me gcc, binutils, etc for arm-none-eabi when I ask it to.
sudo add-apt-repository ppa:germia/archive3 sudo apt-get update
Step 5: Installing packages
sudo apt-get install gcc-arm-none-eabi binutils-arm-none-eabi newlib-arm-none-eabi gdb-arm-none-eabi
Step 6: This would involve going through all the steps given here: imx23-olinuxino.
Step 7: Test your newly built kernel on your olinuxino.
Step 8: If you've come so far, it means you have your cross compile environment setup. Now we'll make a small change to
get a "spidev" device in /dev. Go find
ssp1: ssp@80034000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx23-spi"; pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_a>; status = "okay"; };
with
ssp1: ssp@80034000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx23-spi"; pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_a>; clock-frequency = <1000000>; status = "okay"; spidev: spidev@0 { compatible = "spidev"; spi-max-frequency = <1000000>; reg = <1>; }; };
Step 9: This would give you an "spidev" in /dev/. But there's just one little thing left. Apply this patch, to the kernel.
Step 10: Recompile everything, and you should have a bootstream that will pass the spidev_test. But before you compile it, change
.rx_buf = (unsigned long)rx;
to
.rx_buf = 0;
as iMX233 does not support full-duplex SPI.
Step 11. Compile spidev_test.c. You'd need to cross compile it. Its easiest if you have gcc setup on your olinuxino, I just use my sheevaplug as my cross compile environment. :) If everything goes well you should see something like, this
spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Sspringy is a series of simple toys, made out of cardboard that exhibit funny looking oscillatory motion. They're based on Sarrus linkage implemented using compliant joints.
SideBox is a self-assembled, modular box-style shelf that can be installed on a cubicle divider. Its completely made of corrugated cardboard (one of my favouraite materials), and can be laser-cut to assembled in a matter of 5 minutes. So far I've found them pretty useful as general scratch space, eg pens, headphones, post-it stacks, etc.
This is an interactive installation about a family of curious boxes. The audience interact by closing boxes, the boxes respond by randomly popping open as if curious to know what happened. The boxes are made of 3mm ply. We spent quite a lot of time thinking what could be the simplest opening mechanism. Finally, we settled on a delicately balanced magnetic latch. When not activated, a small magnet in the lid keeps the lid closed against a spring at the back of the box. A solenoid mounted in the base, right across the magnet is activated momentarily with a magnetic field of reverse polarity to open the box. The slight force of repulsion between the magnet and the solenoid is enough to help the spring to pop open the box!
While we were building prototypes of Sohum, sample shipment boxes from Texas Instruments were piling up in our space. I took the opportunity to convert them into this fully functional barstool.
Sohum is an Auditory Evoked Potential acquisition system for resource constrained settings. 3 out of 1000 babies are born with hearing defects. In India, most of these cases go undiagnosed till the age of 2-3 years, when parents finally notice that their child does not speak. Lack of an affordable hearing screening test is one of the reasons. We developed Sohum at Stanford India Biodesign, AIIMS, Delhi for almost one and a half year while trying to raise funds to support development.
Hi, I'm Pragun. I love travelling and making all sorts of things!
Currently, I'm a first year masters student at the Responsive Environments research group at the MIT Media Lab.