<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-5743520447405866726</atom:id><lastBuildDate>Thu, 31 May 2012 20:48:01 +0000</lastBuildDate><category>android</category><category>lego</category><category>quake</category><category>nxt</category><title>Jacek Fedoryński's blog</title><description></description><link>http://blog.jfedor.org/</link><managingEditor>noreply@blogger.com (Jacek Fedoryński)</managingEditor><generator>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-2971451267664298696</guid><pubDate>Tue, 21 Feb 2012 01:16:00 +0000</pubDate><atom:updated>2012-02-21T02:16:50.756+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>android</category><title>Electricity meter fun</title><description>At the place I live, the electricity meter looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-41jCKUqKEgc/T0LrwJY-gDI/AAAAAAAAC7s/3EO7YwjJ9ZQ/s1600/IMG_0294.JPG"&gt;&lt;img border="0" height="300" width="400" src="http://3.bp.blogspot.com/-41jCKUqKEgc/T0LrwJY-gDI/AAAAAAAAC7s/3EO7YwjJ9ZQ/s400/IMG_0294.JPG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The fancy display shows total kilowatt hours and maximum power consumption, but it doesn't show current consumption. Instead it has this blinking red light - the faster it blinks, the higher the power consumption. But to get the actual figure, I'd have to count how many times it blinked, measure the time and then do some arithmetic. And that would be pedestrian. Instead I wrote an application for my phone that does the measurements (with the phone's camera) and displays the current power consumption:&lt;br /&gt;&lt;br /&gt;&lt;iframe width="480" height="360" src="http://www.youtube.com/embed/ysRQ2Ex6DeU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.jfedor.org/misc2/ElectricityMeter.zip"&gt;Here's the source code&lt;/a&gt; if anyone's interested.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-2971451267664298696?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2012/02/electricity-meter-fun.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-41jCKUqKEgc/T0LrwJY-gDI/AAAAAAAAC7s/3EO7YwjJ9ZQ/s72-c/IMG_0294.JPG' height='72' width='72'/><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-1081666863992269714</guid><pubDate>Sat, 31 Dec 2011 15:27:00 +0000</pubDate><atom:updated>2011-12-31T16:33:11.611+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>NXT Drawbot</title><description>When I saw &lt;a href="http://web.me.com/sami6877/unanything/Site/Secret_Work/Entries/2010/6/1_Drawbot.html"&gt;this drawbot&lt;/a&gt;, I immediately thought it was something I should be able to recreate with Lego Mindstorms. And so I did. The idea is simple, there's a pen suspended on thread from motors in the corners. When the motors wind or unwind the thread, the pen moves and draws a line. The rest is a simple application of the Pythagorean theorem to move the pen where we want it.&lt;br /&gt;&lt;br /&gt;&lt;iframe width="480" height="320" src="http://www.youtube.com/embed/bdagQcBHUSQ?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;When watching other drawbots on YouTube etc. I was surprised to see they were able to achieve a level of precision that allows them to recreate pictures by effectively drawing each of their pixels with clever patterns. My bot clearly lacks such precision. I think the main reason for that is the friction between the pen and the drawing surface. Each time the pen is about to start moving, there's a noticeable moment before it breaks away from the static friction. That makes the bot incapable of very small precise movement. There's another source of imprecision - since the radius of the spools that the threads are wound onto is small, the difference in radius when there is no thread wound and when there is a lot of thread wound on the spool is non-negligible.&lt;br /&gt;&lt;br /&gt;Here are &lt;a href="https://plus.google.com/photos/107838661882662102537/albums/5690883081471797825"&gt;some more pictures of the bot&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://plus.google.com/photos/107838661882662102537/albums/5690883081471797825"&gt;&lt;img src="https://lh4.googleusercontent.com/-_DJVqrQsb6Y/TvoUBEglZGI/AAAAAAAACr8/jEP6O5T-ybY/s400/IMG_0043.JPG" width="400" height="300" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-1081666863992269714?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/12/nxt-drawbot.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/bdagQcBHUSQ/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-3991204112454561676</guid><pubDate>Wed, 19 Oct 2011 22:15:00 +0000</pubDate><atom:updated>2011-10-20T00:29:08.784+02:00</atom:updated><title>Google Earth with a PS3 controller</title><description>&lt;p&gt;Google Earth is a lot of fun with a 3D input device. But not everyone can justify shelling out a hundred bucks or so on a &lt;a href="http://www.3dconnexion.com/products/spacenavigator.html"&gt;SpaceNavigator&lt;/a&gt; just to play with Google Earth. I've explored &lt;a href="/2011/10/control-google-earth-with-android.html"&gt;other possibilities&lt;/a&gt;, but the best alternative I've come up with is the PS3 controller. It has more than enough joysticks and buttons for five degrees of freedom. Have a look:&lt;/p&gt; &lt;iframe width="480" height="390" src="http://www.youtube.com/embed/CU2POoEMFrA?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt; &lt;p&gt;The PS3 controller is pretty well supported under Linux (at least if you connect it with a USB cable, it's more complicated if you want to use Bluetooth). The only problem really is mapping its various buttons and joysticks to proper functions in Google Earth. Fortunately, there is a piece of software called &lt;a href="https://launchpad.net/pystromo"&gt;pystromo&lt;/a&gt; that can freely remap input events, thus allowing us to turn a PS3 controller into a SpaceNavigator-lookalike.&lt;/p&gt; &lt;p&gt;Here's what you need to do.&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Download and unpack &lt;a href="https://launchpad.net/pystromo"&gt;pystromo&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Open the &lt;tt&gt;lib/constants.py&lt;/tt&gt; file in the pystromo directory with a text editor. Find the line containing "ABS_MISC" and add the following two lines after that (before the curly brace): &lt;pre&gt;&lt;br /&gt;48: "ABS_L2",&lt;br /&gt;49: "ABS_R2",&lt;br /&gt;&lt;/pre&gt;(We have to do this, because pystromo doesn't have constants for the PS3 controller's L2 and R2 buttons.) &lt;/li&gt;&lt;li&gt;Create a new file in the pystromo directory and call it, say, &lt;tt&gt;config/ps3-ge.map&lt;/tt&gt;. Put the following in it: &lt;pre&gt;&lt;br /&gt;[Device:dualshock]&lt;br /&gt;vendor=0x054c&lt;br /&gt;product=0x0268&lt;br /&gt;&lt;br /&gt;[Map:dualshock]&lt;br /&gt;ABS_X@0~255:ABS_X@0~255&lt;br /&gt;ABS_Y@0~255:ABS_Y@0~255&lt;br /&gt;ABS_Z@0~255:ABS_RZ@0~255&lt;br /&gt;ABS_RZ@0~255:ABS_RX@255~0&lt;br /&gt;ABS_L2@0~255,ABS_R2&lt;1:ABS_Z@127~0&lt;br /&gt;ABS_R2@0~255,ABS_L2&lt;1:ABS_Z@127~255&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Connect your PS3 controller using a USB cable and press the PS button.&lt;/li&gt;&lt;li&gt;As root, run the following command: &lt;tt&gt;./pystromo-remap.py -R -v -m config/ps3-ge.map&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;This will create a new input device, called &lt;tt&gt;eventN&lt;/tt&gt; in &lt;tt&gt;/dev/input/&lt;/tt&gt;. The one you're looking for is the one with the highest number. As root, run this to give your regular user access to the device: &lt;tt&gt;chmod 666 /dev/input/eventN&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;Open &lt;tt&gt;/opt/google/earth/free/drivers.ini&lt;/tt&gt; with a text editor and put the following after the "SETTINGS" line (after the curly brace), remembering to replace &lt;tt&gt;eventN&lt;/tt&gt; with the proper device number: &lt;pre&gt;&lt;br /&gt;SpaceNavigator/sensitivityX = 0.4&lt;br /&gt;SpaceNavigator/sensitivityY = 0.4&lt;br /&gt;SpaceNavigator/sensitivityZ = 0.1&lt;br /&gt;SpaceNavigator/sensitivityPitch = 0.05&lt;br /&gt;SpaceNavigator/sensitivityYaw = 0.05&lt;br /&gt;SpaceNavigator/sensitivityRoll = 100&lt;br /&gt;SpaceNavigator/device = /dev/input/eventN&lt;br /&gt;SpaceNavigator/zeroX = 127&lt;br /&gt;SpaceNavigator/zeroY = 127&lt;br /&gt;SpaceNavigator/zeroZ = 127&lt;br /&gt;SpaceNavigator/zeroPitch = 127&lt;br /&gt;SpaceNavigator/zeroYaw = 127&lt;br /&gt;SpaceNavigator/zeroRoll = 127&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Run Google Earth.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You should now be able to navigate using the left and right sticks and L2/R2 buttons.&lt;/p&gt; &lt;a href="http://4.bp.blogspot.com/-p3WEnNmXNcg/Tp9FoRz1DMI/AAAAAAAACeE/V2PBwxvlwCo/s1600/IMG_0269.JPG" imageanchor="1" style=""&gt;&lt;img border="0" height="240" width="320" src="http://4.bp.blogspot.com/-p3WEnNmXNcg/Tp9FoRz1DMI/AAAAAAAACeE/V2PBwxvlwCo/s320/IMG_0269.JPG" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-3991204112454561676?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/10/google-earth-with-ps3-controller.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/CU2POoEMFrA/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-5030491293961076768</guid><pubDate>Sun, 16 Oct 2011 23:34:00 +0000</pubDate><atom:updated>2011-10-17T01:40:18.937+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>android</category><title>Control Google Earth with an Android tablet</title><description>&lt;p&gt;I have &lt;a href="/2011/08/android-phone-as-touchpad-for-pc.html"&gt;previously described&lt;/a&gt; how to turn an Android device into a mouse under Linux, using the &lt;tt&gt;uinput&lt;/tt&gt; module. There's no reason we should limit ourselves to a simple mouse. Some applications benefit from a multi-axis controller, which we can simulate in a similar way. One such application is Google Earth. Here's a demonstration video: &lt;/p&gt; &lt;iframe width="480" height="390" src="http://www.youtube.com/embed/DmKG6-ZQWWY?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt; &lt;p&gt;And here's how it's done. Just as before, there's an application running on the tablet that listens for touch events and broadcasts them on the network and a Python script running on the computer that listens for those events and translates them to simulated controller events that Google Earth understands. &lt;a href="http://www.jfedor.org/misc2/TouchscreenBroadcaster3D.zip"&gt;Here&lt;/a&gt;'s the tablet application's source code and &lt;a href="http://www.jfedor.org/misc2/TouchscreenBroadcaster3D.apk"&gt;here&lt;/a&gt;'s just the APK if you don't want to compile it yourself. The Python script that's running on the computer is &lt;a href="http://www.jfedor.org/misc2/android3dmouse.zip"&gt;here&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;There are some additional hoops you have to jump through to get it running. &lt;/p&gt; &lt;ul&gt;&lt;li&gt;The Python part requires &lt;a href="http://tjjr.fi/software/python-uinput/"&gt;&lt;tt&gt;python-uinput&lt;/tt&gt;&lt;/a&gt;, which in turn requires &lt;a href="http://tjjr.fi/software/libsuinput/"&gt;&lt;tt&gt;libsuinput&lt;/tt&gt;&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Remember to unblock UDP port 20125 on your computer's firewall, as that's the port that the tablet application uses to broadcast touchscreen events (the tablet and the computer obviously have to be on the same network).&lt;/li&gt;&lt;li&gt;Run &lt;tt&gt;android3dmouse.py&lt;/tt&gt; as root.&lt;/li&gt;&lt;li&gt;Run the TouchscreenBroadcaster3D application on your Android device and touch the screen (the simulated mouse device only appears on the computer after the first events are emitted).&lt;/li&gt;&lt;li&gt;Look in &lt;tt&gt;/dev/input/&lt;/tt&gt; and figure out what the newly created device is called (it's going to be the &lt;tt&gt;eventN&lt;/tt&gt; file with the highest number). &lt;li&gt;As root, execute the following command to let Google Earth running as a regular user access the device: &lt;tt&gt;chmod 666 /dev/input/eventN&lt;/tt&gt;&lt;li&gt;Open &lt;tt&gt;/opt/google/earth/free/drivers.ini&lt;/tt&gt; with a text editor and paste in the following after the "SETTINGS" line (after the curly brace), remembering to replace &lt;tt&gt;eventN&lt;/tt&gt; with the proper device name: &lt;pre&gt;SpaceNavigator/sensitivityX = 80&lt;br /&gt;SpaceNavigator/sensitivityY = 80&lt;br /&gt;SpaceNavigator/sensitivityZ = 30&lt;br /&gt;SpaceNavigator/sensitivityPitch = 0.5&lt;br /&gt;SpaceNavigator/sensitivityYaw = 0.5&lt;br /&gt;SpaceNavigator/sensitivityRoll = 0.5&lt;br /&gt;SpaceNavigator/device = /dev/input/eventN&lt;br /&gt;SpaceNavigator/zeroX = 0.0&lt;br /&gt;SpaceNavigator/zeroY = 0.0&lt;br /&gt;SpaceNavigator/zeroZ = 0.0&lt;br /&gt;SpaceNavigator/zeroPitch = 0.0&lt;br /&gt;SpaceNavigator/zeroYaw = 0.0&lt;br /&gt;SpaceNavigator/zeroRoll = 0.0&lt;br /&gt;SpaceNavigator/gutterValue = 0&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Since X happily grabbed the new device and it now moves the mouse cursor, execute the following command to make X let it go: &lt;tt&gt;xinput set-int-prop "python-uinput-mouse" "Device Enabled" 8 0&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;Finally, run Google Earth.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You should now be able to pan, zoom and rotate via multi-touch gestures on your tablet's (or phone's) screen. (Yes, one more degree of freedom would be nice, but I haven't figured out a good way to do it yet.) &lt;/p&gt; &lt;p&gt;If you can't get this mess to work, I'm not the first one to do something like this, there's a Google Summer of Code project done by Reese Butler that works in a similar manner, but uses a slightly different control scheme. The Android part is &lt;a href="https://market.android.com/details?id=com.lg.accel"&gt;on the Market&lt;/a&gt; and the computer part can be found &lt;a href="https://github.com/reesebutler/Android-accelerometer-and-touch-screen-control"&gt;here&lt;/a&gt;. Maybe you'll have more luck with that one. &lt;/p&gt; &lt;a href="http://3.bp.blogspot.com/-PMoWCu6Z2XU/Tptc85tqI9I/AAAAAAAACcY/ZJE0AQJ6xYI/s1600/IMG_0266.JPG" imageanchor="1" style=""&gt;&lt;img border="0" height="240" width="320" src="http://3.bp.blogspot.com/-PMoWCu6Z2XU/Tptc85tqI9I/AAAAAAAACcY/ZJE0AQJ6xYI/s320/IMG_0266.JPG" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-5030491293961076768?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/10/control-google-earth-with-android.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/DmKG6-ZQWWY/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-4628949956810574415</guid><pubDate>Fri, 19 Aug 2011 21:52:00 +0000</pubDate><atom:updated>2011-10-17T01:41:05.289+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>android</category><title>Android phone as a touchpad for a PC</title><description>The Linux kernel has a module named &lt;tt&gt;uinput&lt;/tt&gt; that allows userspace programs to simulate input devices like mice, keyboards and joysticks. I used this neat mechanism to turn my Android phone into a touchpad for my computer.&lt;br /&gt;&lt;br /&gt;&lt;iframe width="480" height="390" src="http://www.youtube.com/embed/n7uxLHRAnaQ?rel=0"  frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Here's how it works. On the phone there's an application that broadcasts touchscreen events over the network. You can get the application's source &lt;a href="http://www.jfedor.org/misc2/TouchscreenBroadcaster.zip"&gt;here&lt;/a&gt;. On the PC there's a script running that listens for the events and translates them into mouse events that get injected into the system via &lt;tt&gt;uinput&lt;/tt&gt;, at which point the X server sees them and moves the mouse pointer accordingly. That part is written in Python and requires the &lt;a href="http://tjjr.fi/software/python-uinput/"&gt;&lt;tt&gt;python-uinput&lt;/tt&gt;&lt;/a&gt; module (which in turn requires &lt;a href="http://tjjr.fi/software/libsuinput/"&gt;&lt;tt&gt;libsuinput&lt;/tt&gt;&lt;/a&gt;). You can get its source &lt;a href="http://www.jfedor.org/misc2/androidmouse.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As always, there's room for improvement. I used my phone's trackball as left mouse button, but for phones or tablets that have no trackball it would probably make sense to use some regions of the screen as buttons. It would also be interesting to add multitouch gestures for scrolling and zooming. Another thing that comes to mind is to use the phone as a 3D controller for Google Earth. Four degrees of freedom should be doable with the touchscreen alone via two-finger gestures and maybe we could use the phone's other sensors like the accelerometer and gyroscope (which my Nexus One lacks, but newer phones have them) to get all six.&lt;br /&gt;&lt;br /&gt;&lt;img border="0" height="240" width="320" src="http://1.bp.blogspot.com/-509KiIL56LI/Tk7YDKI0GMI/AAAAAAAACVU/4itlD7FBweg/s320/androidmouse.jpg" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-4628949956810574415?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/08/android-phone-as-touchpad-for-pc.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/n7uxLHRAnaQ/default.jpg' height='72' width='72'/><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-7996914817803657821</guid><pubDate>Sun, 03 Jul 2011 20:31:00 +0000</pubDate><atom:updated>2011-07-03T22:31:14.260+02:00</atom:updated><title>On keyboards</title><description>Many people don't care about keyboards. I do. But unlike most keyboard enthusiasts, who focus on the switches (mechanical vs. rubber dome etc.) and are prepared to give long lectures on buckling springs and how the &lt;a href="http://en.wikipedia.org/wiki/Model_M_keyboard"&gt;IBM Model M&lt;/a&gt; is the greatest keyboard of all time (which is probably true), I don't care that much about switches. I can't stand keyboards with wrong key layouts. I don't mean Dvorak vs. QWERTY, I mean the physical layout of the keys. And by "wrong" I mean pretty much any layout that's different from the standard full-size one. (That's one of the reasons I don't see myself using a laptop for anything serious anytime soon.)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-2otaAnLd3NA/ThCecb2AO1I/AAAAAAAACIM/COZ16NFXEDE/s1600/menu_key.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="90" width="140" src="http://4.bp.blogspot.com/-2otaAnLd3NA/ThCecb2AO1I/AAAAAAAACIM/COZ16NFXEDE/s140/menu_key.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Fortunately, most full-size keyboards have sane key layouts. There are two issues with modern keyboards that drive me crazy. One is the "menu" key introduced by Microsoft some time around Windows 95. Notice that I don't even mind the Windows logo keys that much. An additional modifier key is sometimes useful. Mac keyboards have three modifier keys on the bottom row, classic Unix keyboards often had them as well. I don't even care that it's the Windows logo, not some OS-agnostic symbol. But the "menu" key? What is it for? I don't think I've ever seen it used for anything. It's useless and it messes up the symmetry of the layout (three modifier keys on each side of the space bar). It also means the space bar is too short. So that's the first of my keyboard-related pet peeves. As you're about to see, I care about the second one much more deeply.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-cXpZhZiQwCo/ThCl-IB8QAI/AAAAAAAACIc/I_NNzqFMaek/s1600/numeric_keypad.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="140" width="113" src="http://3.bp.blogspot.com/-cXpZhZiQwCo/ThCl-IB8QAI/AAAAAAAACIc/I_NNzqFMaek/s140/numeric_keypad.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Numeric keypads. I hate them. I guess they're useful if you're an accountant and must input a lot of numbers into your spreadsheets. I'm not an accountant. I imagine to most people the numeric keypad is as useless as it is to me. The last time I remember using it is when we were playing Mortal Kombat fifteen years ago. So what, I hear you say. Just don't use it. But you see, it takes up space that I need for something else, namely the mouse. I need my keyboard positioned so that the monitor's symmetry axis goes between the G and H keys. That way my arms are positioned in a natural symmetric way when typing. That means that if my keyboard has a numeric keypad, the mouse goes too far to the right. I'm pretty sure it's not just annoying, but also not good for my posture.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-FIWQxi-yoYE/ThCkUJLHafI/AAAAAAAACIU/PgfrAroTZj8/s1600/keyboard_axis.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="300" width="400" src="http://2.bp.blogspot.com/-FIWQxi-yoYE/ThCkUJLHafI/AAAAAAAACIU/PgfrAroTZj8/s400/keyboard_axis.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;What can we do about this sad state of affairs? Aren't there any good keyboards? Well, there are. Bad news is, they're not exactly cheap. I have two candidates for "the perfect keyboard". One is the space saving variant of the previously mentioned Model M:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-31oRfXBvUVo/ThCoLn6jqtI/AAAAAAAACIk/RwZJtrNT2IY/s1600/model_m_space_saving.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="199" width="400" src="http://4.bp.blogspot.com/-31oRfXBvUVo/ThCoLn6jqtI/AAAAAAAACIk/RwZJtrNT2IY/s400/model_m_space_saving.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In a lot of ways, it is the Holy Grail. An elegant weapon for a more civilized age. No numeric keypad, no stupid Windows keys. Built like a tank. Likely to outlive its user.  There are downsides though. And I'm not even talking about the loud click, which is sure to drive your coworkers and roommates crazy. Problem is, the keyboard is long out of production and it is the less popular variant of the Model M. So when one of them shows up on eBay, it easily goes for more than 200 USD.&lt;br /&gt;&lt;br /&gt;Is there no keyboard with all the right features that is still in production? As it happens, there is, the Realforce 86U:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-akKKUd9bnkQ/ThCo2lsQ6HI/AAAAAAAACIs/MoojEHKNdm4/s1600/realforce_86u.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="267" width="400" src="http://1.bp.blogspot.com/-akKKUd9bnkQ/ThCo2lsQ6HI/AAAAAAAACIs/MoojEHKNdm4/s400/realforce_86u.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, it has the Windows logo keys, but as I said, they don't bother me. What's important is that there's no "menu" key next to the right Control. And no numeric keypad of course. What's the catch? The keyboard might be in production, but it doesn't mean it's cheap. It currently goes for 265 USD &lt;a href="http://www.elitekeyboards.com/products.php?sub=topre_keyboards,rftenkeyless&amp;pid=rf_se0500"&gt;on EliteKeyboards&lt;/a&gt;. Ouch.&lt;br /&gt;&lt;br /&gt;I'm not aware of any cheaper keyboards that would match all my criteria (no menu key, no numeric keypad, standard full-size layout otherwise). If you're not ready to shell out two hundred bucks or more on a keyboard, you have to start making compromises. The one I'm probably willing to make is to accept the menu key. I still think it's extremely idiotic, but I guess I can live with it. If we allow the menu key, that opens up several possibilities in the 100-150 USD range. EliteKeyboards currently carries &lt;a href="http://www.elitekeyboards.com/products.php?sub=leopold"&gt;some nice keyboards from Leopold&lt;/a&gt; and Amazon has &lt;a href="http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&amp;field-keywords=majestouch+tenkeyless&amp;x=0&amp;y=0"&gt;several Filco Majestouch keyboards&lt;/a&gt; to choose from. Both brands seem reasonable, but they're still a bit pricey. Like I said, most keyboard geeks obsess about the mechanical switches ("Cherry" switches in the case of Leopolds and Filcos) and they don't come cheap.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-RGRkW8buJfU/ThDEMSZ6YJI/AAAAAAAACI0/r7etFdNZyWY/s1600/leopold_tenkeyless.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="125" width="230" src="http://2.bp.blogspot.com/-RGRkW8buJfU/ThDEMSZ6YJI/AAAAAAAACI0/r7etFdNZyWY/s230/leopold_tenkeyless.jpg" /&gt;&lt;/a&gt;&lt;a href="http://1.bp.blogspot.com/-6fZE-hAQuUg/ThDEQWpBP8I/AAAAAAAACI8/ZBbLiLgrHHk/s1600/filco_majestouch_tenkeyless.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="125" width="230" src="http://1.bp.blogspot.com/-6fZE-hAQuUg/ThDEQWpBP8I/AAAAAAAACI8/ZBbLiLgrHHk/s230/filco_majestouch_tenkeyless.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;An important thing to know when looking for keyboards with no numeric keypad is that they're called "tenkeyless". Don't waste your time looking for "space saver" keyboards as they're almost always some ugly layouts that keep the numeric keypad, but drop the arrow keys/page up/page down area (a notable exception is the Model M mentioned above). I really don't understand the thinking behind such layouts. What I understand even less are the laptop keyboards with numeric keypads. And they are getting popular. I guess on 15-inch and bigger laptops there is enough space for extra keys, but why would you waste it on a numeric keypad and not, say, reasonable sized arrow keys and page up/page down etc. Another problem with such laptops is the already mentioned asymmetry. It's impossible to position your arms comfortably when typing, when the home row of the keyboard is shifted to the left (and obviously you can't reposition the laptop's keyboard in relation to the screen).&lt;br /&gt;&lt;br /&gt;One day Logitech will make a nice, cheap, "tenkeyless" keyboard. But it probably won't be tomorrow, so what can you do in the mean time? Well, you can take inspiration from &lt;a href="http://tlb.org/keyboardchop.html"&gt;this guy&lt;/a&gt;, who shares my dislike for numeric keypads, take a keyboard that has a numeric keypad and... chop it off. It's what I did to a Logitech UltraX:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-4-NLlrLFJ_c/ThCcXST33xI/AAAAAAAACIE/uPnucRjd7KI/s1600/keyboard_lobotomy.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="201" width="400" src="http://3.bp.blogspot.com/-4-NLlrLFJ_c/ThCcXST33xI/AAAAAAAACIE/uPnucRjd7KI/s400/keyboard_lobotomy.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It turned out to be more difficult than I thought (the keyboard looks cheap, but there's a metal plate inside that I had to saw off) and it may not look pretty, but in the end I have a keyboard with a reasonable layout that didn't cost an arm and a leg. If you want to try it yourself, some instructions can be found &lt;a href="http://www.wikihow.com/Cut-the-Number-Pad-off-a-Keyboard"&gt;on wikiHow&lt;/a&gt;. Obviously the details will depend on the exact keyboard model that you choose to lobotomize.&lt;br /&gt;&lt;br /&gt;If you're considering becoming a keyboard otaku, I strongly recommend that you check out &lt;a href="http://geekhack.org/"&gt;geekhack.org&lt;/a&gt;, they have an active forum and a wiki with more information on keyboard switches than a sane person needs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-7996914817803657821?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/07/on-keyboards.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-2otaAnLd3NA/ThCecb2AO1I/AAAAAAAACIM/COZ16NFXEDE/s72-c/menu_key.jpg' height='72' width='72'/><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-757509176411379158</guid><pubDate>Thu, 05 May 2011 22:14:00 +0000</pubDate><atom:updated>2011-05-06T00:14:20.973+02:00</atom:updated><title>Dominoes</title><description>A few years ago I was briefly interested in physics engines. Nothing ever came out of it, but I did make a few experiments. Here's one of them:&lt;br /&gt;&lt;br /&gt;&lt;iframe width="480" height="310" src="http://www.youtube.com/embed/Qh5CtRGZ-rg?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;It uses the &lt;a href="http://bulletphysics.org/"&gt;Bullet&lt;/a&gt; engine and I'm actually quite surprised that I bothered to make a relatively polished interface for placing the tiles. I was somewhat less surprised with the fact that it didn't compile after sitting on my hard drive for a few years. It turns out that there were some incompatible changes in Bullet since then, so I had to make a few modifications to make it run with recent versions.&lt;br /&gt;&lt;br /&gt;If you want to play with it yourself, &lt;a href="http://www.jfedor.org/misc/domino.tar.gz"&gt;here's the code&lt;/a&gt; (be warned it's ugly inside, though).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-NIYq2thi3OI/TcMcPk--A-I/AAAAAAAACBc/0pDWCoUKPGo/s1600/domino.png" imageanchor="1" style=""&gt;&lt;img border="0" height="274" width="400" src="http://2.bp.blogspot.com/-NIYq2thi3OI/TcMcPk--A-I/AAAAAAAACBc/0pDWCoUKPGo/s400/domino.png" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-757509176411379158?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/05/dominoes.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/Qh5CtRGZ-rg/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-5425628134048731170</guid><pubDate>Fri, 22 Apr 2011 15:00:00 +0000</pubDate><atom:updated>2011-04-22T17:00:13.916+02:00</atom:updated><title>Hippo Paint</title><description>My three year old niece likes to sit in front of Google Image Search and look at pictures of dinosaurs (and frankly, who doesn't?). Every once in a while there's a coloring book style picture and she wants to paint it. The best I could come up with on short notice was to print out the picture and give her crayons. But obviously there had to be a better way.&lt;br /&gt;&lt;br /&gt;Enter &lt;a href="http://www.hippopaint.com/"&gt;Hippo Paint&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.hippopaint.com/" imageanchor="1" style=""&gt;&lt;img border="0" height="335" width="440" src="http://1.bp.blogspot.com/-5MPPTnc1wkw/TbGNRQT0ghI/AAAAAAAACA8/TR9OdAf_bhY/s440/hippopaint-screenshot2.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It should work in all modern browsers (it even works in IE9). While making this I could clearly see that JavaScript engines in browsers really are getting faster (for example there's a big difference between Firefox 3.6.x and 4.0), but you still have to make all the trivial optimizations like function inlining or common subexpression elimination by hand.&lt;br /&gt;&lt;br /&gt;I also encountered an interesting bug that only manifested itself in Opera. I had a piece of code that looked something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;var img = new Image();&lt;br /&gt;img.onload = function() { /* ... */ };&lt;br /&gt;img.src = '...';&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And sometimes the &lt;code&gt;onload&lt;/code&gt; handler function wasn't getting called (even though I could see that the image was successfully fetched from the network). After a frustrating debugging session I noticed that it only happened when fetching the image took longer than usual (say, more than a second). It turns out that it gave Opera's garbage collector enough time to kick in and collect my &lt;code&gt;img&lt;/code&gt; variable. I don't know if other browsers don't have as aggressive garbage collectors or if they think that the existence of an event handler is enough to mark the variable as still needed. Anyway, the solution was simply to move the variable to an outer scope.&lt;br /&gt;&lt;br /&gt;I hope you and your kids have as much fun using &lt;a href="http://www.hippopaint.com/"&gt;Hippo Paint&lt;/a&gt; as I had making it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-5425628134048731170?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/04/hippo-paint.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-5MPPTnc1wkw/TbGNRQT0ghI/AAAAAAAACA8/TR9OdAf_bhY/s72-c/hippopaint-screenshot2.png' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-8487757241367677970</guid><pubDate>Wed, 30 Mar 2011 21:54:00 +0000</pubDate><atom:updated>2011-03-31T00:03:06.667+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>android</category><title>Pivot screen fun</title><description>I used to think pivot monitors were only good for &lt;a href="https://lh6.googleusercontent.com/_5TvSUp77d78/TUnSZ4yVu3I/AAAAAAAAB3Q/kwAbI-hPF3g/s800/%5BUNSET%5D.jpg"&gt;playing Pac-Man&lt;/a&gt; in portrait position. But why restrict ourselves to just the landscape and portrait positions?&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" width="480" height="390" src="http://www.youtube.com/embed/SfTYao_LUHk?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Since the monitor only knows two states, I had to resort to a little trick. I attached my phone to the back of the monitor and wrote an application that broadcasts orientation data from the phone's accelerometer on the network. On the computer, another application receives the data and rotates the teapot accordingly. (Here's the &lt;a href="http://www.jfedor.org/misc2/OrientationBroadcaster.zip"&gt;source code to the phone application&lt;/a&gt; and &lt;a href="http://www.jfedor.org/misc2/teapot.zip"&gt;the teapot application&lt;/a&gt; if you're interested.)&lt;br /&gt;&lt;br /&gt;What I really wanted to do was to make the desktop rotate with all the windows. I think it should be possible with &lt;a href="http://en.wikipedia.org/wiki/Compiz"&gt;Compiz&lt;/a&gt;, but I'm pretty sure it would prove difficult enough for me to lose interest halfway through. So, a teapot for now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-8487757241367677970?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/03/pivot-screen-fun.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/SfTYao_LUHk/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-6435780499638043850</guid><pubDate>Thu, 17 Feb 2011 02:57:00 +0000</pubDate><atom:updated>2011-02-17T04:06:04.506+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>android</category><title>Morse Code Reader</title><description>I wanted to make a Morse code reading application for some time now. Here's my first attempt, it listens to the signal through the phone's mic and translates it to text:&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" width="480" height="390" src="http://www.youtube.com/embed/FHO8U9pe-6E?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;I'm sure there are all kinds of advanced signal processing techniques that I should be using, but for now I went with the simplest, most naive approach. And it sort of works, except when it doesn't. What I do is I keep an exponential moving average of the signal's volume and I decide that the signal is currently "high" when the average is above a threshold and "low" when it's below it. The threshold is set based on recent peak volume. Then I try to decide what the length of a dot and a dash is, interpret the input accordingly, and finally translate the dots and dashes to letters. The application adapts to changing volume and speed within reasonable limits (it should work up to about 40 WPM).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-SWAREAnwav4/TVyKvw_DPeI/AAAAAAAAB6M/F4LYd8v_YKs/s1600/morse_shot2b.png" imageanchor="1" style=""&gt;&lt;img border="0" height="288" width="480" src="http://1.bp.blogspot.com/-SWAREAnwav4/TVyKvw_DPeI/AAAAAAAAB6M/F4LYd8v_YKs/s480/morse_shot2b.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I was hesitant about putting the application on Android Market, as I only tested it on my phone and it quite often fails at translating Morse code. Then again, it's not like I have anything to lose by getting 1-star reviews and insulting comments, so why not.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://market.android.com/details?id=org.jfedor.morsecode"&gt;Here's a Market link&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://market.android.com/details?id=org.jfedor.morsecode"&gt;&lt;img src="http://chart.apis.google.com/chart?cht=qr&amp;chs=230x230&amp;chl=market%3A%2F%2Fdetails%3Fid%3Dorg.jfedor.morsecode" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-6435780499638043850?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/02/morse-code-reader.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/FHO8U9pe-6E/default.jpg' height='72' width='72'/><thr:total>4</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-6910161572910932714</guid><pubDate>Fri, 28 Jan 2011 02:48:00 +0000</pubDate><atom:updated>2011-01-28T03:48:42.815+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>Page turner Mark II</title><description>I have improved &lt;a href="http://blog.jfedor.org/2011/01/automatic-page-turner.html"&gt;my initial page turner design&lt;/a&gt;. Thanks to a third motor that repositions the rubber wheel between the left and right of the book, we can now turn pages in both directions!&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" class="youtube-player" type="text/html" width="480" height="320" src="http://www.youtube.com/embed/5u8WSbI4n64?rel=0" frameborder="0" allowFullScreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;The device is still manually operated and the problem of sometimes grabbing more than one page remains. But it is now less of a problem, because if we go a few pages too far, we can always go back.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/TGQo9xb_P4vOdLrg2svqULl3vWWphC7OmI3Dbsz6UCo?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_5TvSUp77d78/TUIllMJZkbI/AAAAAAAAB20/ETuSY1ENIT8/s400/IMG_20110128_024147.jpg" height="300" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/1tE7PGp_dvLgXvSc8MOi5Ll3vWWphC7OmI3Dbsz6UCo?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_5TvSUp77d78/TUIlrBgqF-I/AAAAAAAAB24/qDweqyGb9LU/s400/IMG_20110128_024156.jpg" height="300" width="400" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-6910161572910932714?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/01/page-turner-mark-ii.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/5u8WSbI4n64/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-3650670772363265116</guid><pubDate>Thu, 27 Jan 2011 01:43:00 +0000</pubDate><atom:updated>2011-01-27T02:43:26.189+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>Automatic page turner</title><description>Reading books is hard enough as it is. They're often long, boring and some don't even have any pictures in them. I decided to at least eliminate the physical effort of turning pages and constructed this little device:&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" class="youtube-player" type="text/html" width="480" height="320" src="http://www.youtube.com/embed/b4vtJnKFtM8?rel=0" frameborder="0" allowFullScreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;At the moment it's not entirely automatic as I'm still controlling the individual motors manually (via Bluetooth from my phone, which is off-screen, because I'm also using it to shoot the video). The setup requires some tweaking for the exact size of the book and probably only works for a certain range of pages in the middle of the book. It also still sometimes grabs more than one page. But hey, it's a start. There's obviously room for improvement, for example it would be nice to be able to turn the pages in both directions.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/dvBVQynSU9gRhQbBbV2WfLl3vWWphC7OmI3Dbsz6UCo?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_5TvSUp77d78/TUB3UYnAfUI/AAAAAAAAB2g/ZfStuwkSEvQ/s400/IMG_20110125_015405.jpg" height="300" width="400" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-3650670772363265116?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/01/automatic-page-turner.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/b4vtJnKFtM8/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-6219304228333471015</guid><pubDate>Tue, 18 Jan 2011 03:36:00 +0000</pubDate><atom:updated>2011-01-18T04:36:01.604+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>NXT powered globe</title><description>OK, so this one isn't terribly sophisticated, but anyway. I attached an NXT motor to a globe:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh3.ggpht.com/_5TvSUp77d78/TTUFaHtJ8fI/AAAAAAAAB1w/Tni4o3QAN_8/s400/IMG_20110118_041213.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Here it is in motion (apologies for the low quality, I had to jump through some hoops to shoot video and control the Mindstorms brick from my phone at the same time):&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" class="youtube-player" type="text/html" width="480" height="390" src="http://www.youtube.com/embed/eeSehXc8m8Q?rel=0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-6219304228333471015?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2011/01/nxt-powered-globe.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_5TvSUp77d78/TTUFaHtJ8fI/AAAAAAAAB1w/Tni4o3QAN_8/s72-c/IMG_20110118_041213.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-6330485493197639470</guid><pubDate>Fri, 12 Nov 2010 22:08:00 +0000</pubDate><atom:updated>2011-01-18T04:36:27.070+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>android</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>NXT Remote Control</title><description>Two of my favorite toys right now are my Lego Mindstorms set and my Android phone. And thanks to the Bluetooth protocol I've found a way to combine them. Behold!&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" class="youtube-player" type="text/html" width="480" height="390" src="http://www.youtube.com/embed/egllcH-0rQ0?rel=0" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Since the video is quite blurry, here's a better view of the application's interface:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_5TvSUp77d78/TN2hEMjYfLI/AAAAAAAABxc/uy_PCaOvKts/s1600/nxt_shot3.png"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/_5TvSUp77d78/TN2hEMjYfLI/AAAAAAAABxc/uy_PCaOvKts/s320/nxt_shot3.png" width="214" /&gt;&lt;/a&gt;&lt;a href="http://4.bp.blogspot.com/_5TvSUp77d78/TN2hEfCylSI/AAAAAAAABxg/iS5gWAnqNvM/s1600/nxt_shot4.png"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_5TvSUp77d78/TN2hEfCylSI/AAAAAAAABxg/iS5gWAnqNvM/s320/nxt_shot4.png" width="214" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The third control scheme (not pictured), which I like to call the tank mode, allows you to control each motor separately and works best if your phone has true multitouch support (not just pinch-to-zoom).&lt;br /&gt;&lt;br /&gt;Now I'm not saying my application is very unique, there are at least two others on the Android Market that do the same, including an official one from Lego. But hey, it's mine!&lt;br /&gt;&lt;br /&gt;If you'd like to try it, below is a QR code that you can scan from your phone (or if you're reading this on your phone, just tap the code). And here's the application's &lt;a href="http://www.appbrain.com/app/nxt-remote-control/org.jfedor.nxtremotecontrol"&gt;AppBrain page&lt;/a&gt;. (It's free of course.)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://market.android.com/search?q=pname:org.jfedor.nxtremotecontrol"&gt;&lt;img border="0" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=230x230&amp;chl=market://search%3Fq%3Dpname:org.jfedor.nxtremotecontrol" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Finally if you'd like to see the source code, it's &lt;a href="http://code.google.com/p/nxt-remote-control/"&gt;over here&lt;/a&gt; at Google Code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-6330485493197639470?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/11/nxt-remote-control.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/egllcH-0rQ0/default.jpg' height='72' width='72'/><thr:total>4</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-5086362226755608471</guid><pubDate>Sat, 23 Oct 2010 02:53:00 +0000</pubDate><atom:updated>2010-10-23T04:53:55.320+02:00</atom:updated><title>Paper clip spinning top</title><description>Today I'm going to show you how to make a spinning top from a paper clip. If you have a three year old niece or nephew, this is a trick you must learn.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_5TvSUp77d78/TMJDYEIu2LI/AAAAAAAABw4/yexpcOw4RP4/s800/paper_clip_spinning_top.jpg"&gt;&lt;br /&gt;&lt;br /&gt;You're going to need a paper clip and a pair of pliers. Also some cylindrical object is helpful, but not strictly necessary (I used a screwdriver handle). The paper clip can be any size, I used the bigger kind for demonstration, but the smaller ones work, too.&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" class="youtube-player" type="text/html" width="480" height="390" src="http://www.youtube.com/embed/sYoJ0EwEOx8?rel=0" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Supposedly the angle between the spokes must be 53 degrees for the center of gravity to be on the axis, but in my experience any roughly pac-man-like shape works. With a bit of tweaking you should get a top that spins for at least 30 seconds on a reasonably smooth surface.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-5086362226755608471?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/10/paper-clip-spinning-top.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_5TvSUp77d78/TMJDYEIu2LI/AAAAAAAABw4/yexpcOw4RP4/s72-c/paper_clip_spinning_top.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-4328974436341010415</guid><pubDate>Sat, 09 Oct 2010 22:55:00 +0000</pubDate><atom:updated>2011-01-18T04:36:53.235+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>quake</category><title>Panoramic Quake 3</title><description>&lt;a href="http://blog.jfedor.org/2010/10/my-ghetto-liquid-galaxy-setup.html"&gt;Running Google Earth on five screens&lt;/a&gt; is pretty cool, but we all know that the real test for any computer system is whether it can run Quake. Today I'm going to show you how to run Quake III Arena in a panoramic multiple screen configuration. Here's what my setup looks like:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/af8lnR-bHDpdYqfd5fSC2ECSrkEXeNXe3GUh1uuqY-I?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_5TvSUp77d78/TLDLVNGRjyI/AAAAAAAABvU/9uc5Wv8C_9M/s400/IMG_20101009_211805.jpg" height="300" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And here's a video of me playing with some bots:&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" class="youtube-player" type="text/html" width="480" height="390" src="http://www.youtube.com/embed/ncZCOtQXzGQ?rel=0" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;How do you make it work like that?&lt;br /&gt;&lt;br /&gt;It turns out that it's actually easier than it seems, as Quake 3 already includes the view synchronization functionality, because it's needed for spectators. The only thing that we need in addition to that is a way to rotate the view a little to the left or to the right. &lt;a href="http://www.jfedor.org/misc/ioquake3-liquid-galaxy.diff"&gt;This simple patch&lt;/a&gt; does exactly that, introducing a new console variable named &lt;code&gt;cg_yawOffset&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;You're going to need:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;five monitors and five computers (or some other number)&lt;/li&gt;&lt;li&gt;a working copy of &lt;a href="http://ioquake3.org/"&gt;ioquake3&lt;/a&gt; on each of them&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.jfedor.org/misc/ioquake3-liquid-galaxy.zip"&gt;my mod&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;(Technically, you don't need a separate machine for each screen, you could drive two or more screens from the same computer if you figure out how to make one instance of Quake 3 run in fullscreen on one monitor and another one on the other. Also, there's nothing ioquake3-specific about my mod, it's just that I used ioquake3 to compile it, so it uses the new QVM format, which doesn't work with vanilla Quake 3. If you want to make it work with vanilla Quake 3, you'll have to take my patch and compile it yourself.)&lt;br /&gt;&lt;br /&gt;Unzip my mod and put the &lt;code&gt;galaxy&lt;/code&gt; directory in your ioquake3 directory (it has to be on the same level as the &lt;code&gt;baseq3&lt;/code&gt; directory). Do it on every computer. The mod consists of QVM files and not native code, so it's platform independent and can't hurt your computer, so don't worry.&lt;br /&gt;&lt;br /&gt;For simplicity I'm going to assume that you're going to play using the computer connected to the screen in the center, even though it doesn't have to be that way. The server is also going to run on it. On that computer, run ioquake3 with the following command line parameters:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;+set fs_game galaxy +set sv_pure 0 +devmap q3dm7&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(You can use some other map if you like.)&lt;br /&gt;&lt;br /&gt;On the rest of the machines, just run ioquake3 as you normally would. Then connect to the server, either by typing &lt;code&gt;\connect server_ip&lt;/code&gt; in the console (you'll have to know the server's IP address) or from the menu. Then become a spectator, by typing &lt;code&gt;\team s&lt;/code&gt; in the console or from the menu (press Esc, choose &lt;i&gt;start&lt;/i&gt;, then &lt;i&gt;spectate&lt;/i&gt;). Then click the left mouse button (or whatever you have bound to &lt;code&gt;+attack&lt;/code&gt;) until you're following the player from the master computer (center screen). All your screens should now be displaying the same view.&lt;br /&gt;&lt;br /&gt;Time for the real magic. On each computer, type &lt;code&gt;\cg_fov 45&lt;/code&gt; in the console to set the field of view (use a number that matches the geometry of your setup, 45 degrees is what I used). Then on the first computer to the left of the master, type &lt;code&gt;\cg_yawOffset 45&lt;/code&gt;. That will rotate the view 45 degrees to the left (if you used something other than 45 degrees for the FOV, use the same number here). On the second computer to the left, type &lt;code&gt;\cg_yawOffset 90&lt;/code&gt; and on the computers to the right, type &lt;code&gt;\cg_yawOffset -45&lt;/code&gt; and &lt;code&gt;\cg_yawOffset -90&lt;/code&gt;. You should now have a nice panoramic Quake 3 configuration. Move around and see if everything works as it should.&lt;br /&gt;&lt;br /&gt;You'll also want to disable the gun and the HUD on all screens except the master. To do that, type &lt;code&gt;\cg_drawGun 0&lt;/code&gt; and &lt;code&gt;\cg_draw2D 0&lt;/code&gt; in the console.&lt;br /&gt;&lt;br /&gt;Oh, and by the way, if you don't have the full version of Quake 3, all of this works fine with the &lt;code&gt;pak0.pk3&lt;/code&gt; from the demo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-4328974436341010415?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/10/panoramic-quake-3.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_5TvSUp77d78/TLDLVNGRjyI/AAAAAAAABvU/9uc5Wv8C_9M/s72-c/IMG_20101009_211805.jpg' height='72' width='72'/><thr:total>3</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-8398932679312144661</guid><pubDate>Fri, 01 Oct 2010 17:53:00 +0000</pubDate><atom:updated>2010-10-01T19:57:08.788+02:00</atom:updated><title>My ghetto Liquid Galaxy setup</title><description>Yesterday Google has published instructions on how to recreate their &lt;a href="http://code.google.com/p/liquid-galaxy/"&gt;Liquid Galaxy&lt;/a&gt; immersive environment for Google Earth. Naturally I had to try it immediately. Unfortunately I don't have access to eight 55-inch monitors, so my setup is not quite as impressive as Google's, but still very neat:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/z2ZJQ0xmCEY-HvttwXegbu3R3RMQSsAIR7rzt0jCpoc?feat=embedwebsite"&gt;&lt;img height="300" src="http://lh5.ggpht.com/_5TvSUp77d78/TKYXLTCFpKI/AAAAAAAABt8/DBQif9fSTqs/s400/IMG_20101001_161936.jpg" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here it is in action:&lt;br /&gt;&lt;br /&gt;&lt;iframe class="youtube-player" frameborder="0" height="390" src="http://www.youtube.com/embed/by6fF3QT5Q8" title="YouTube video player" type="text/html" width="480"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe class="youtube-player" frameborder="0" height="390" src="http://www.youtube.com/embed/nue9yYHsfhA" title="YouTube video player" type="text/html" width="480"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-8398932679312144661?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/10/my-ghetto-liquid-galaxy-setup.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_5TvSUp77d78/TKYXLTCFpKI/AAAAAAAABt8/DBQif9fSTqs/s72-c/IMG_20101001_161936.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-4651282954425393496</guid><pubDate>Fri, 20 Aug 2010 17:09:00 +0000</pubDate><atom:updated>2010-10-23T04:37:27.845+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>Line Following Robot</title><description>Everyone with a Lego Mindstorms set must at some point build a line following robot. Here's mine.&lt;br /&gt;&lt;br /&gt;&lt;iframe class="youtube-player" type="text/html" width="480" height="385" src="http://www.youtube.com/embed/7XL83VGEYjU?hl=en_US" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;The trick to following a line when all you have is one light sensor is that you don't follow the line, you follow the line's right (or left) edge. You try to stay exactly on the border between the dark area and the light area. The light sensor reports shades of gray when it passes from black to white. You choose a value that you think corresponds to the edge and then when the sensor reports a value brighter than the threshold value, you turn left, and when it reports a value darker than the threshold value, you turn right (assuming you chose to follow the right edge of a black line).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/3NP1KvhMaY-APG5pjltqHQ?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_5TvSUp77d78/TG6UUioXs8I/AAAAAAAABrs/uV7J9Ls0ep8/s400/IMG_20100820_163836.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For smooth movement we don't just turn left when the value from the sensor is greater than the chosen threshold. Since the data we get is not binary, we can make the robot turn sharper when we think it's off the line entirely and only adjust its course slightly when we think it has left the edge of the line, but by just a little.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/km12fAxagap8tO7BNUd3Jw?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_5TvSUp77d78/TG6UelUQW0I/AAAAAAAABrs/OImaYlApw08/s400/IMG_20100820_163926.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's the &lt;a href="http://www.jfedor.org/lego/linefollower.nxc"&gt;NXC program&lt;/a&gt; that the robot is running. It's heavily inspired by the NXT-G program of &lt;a href="http://nxtprograms.com/NXT2/line_follower/index.html"&gt;this robot&lt;/a&gt;. I initially used &lt;tt&gt;OnFwdSync(OUT_BC, ...)&lt;/tt&gt; to turn the robot, but it sometimes resulted in very jerky movement. When trying to figure out whether it's a problem with my hardware or software I looked at that robot's program and saw that they control each motor independently. When I replaced calls to &lt;tt&gt;OnFwdSync(OUT_BC, ...)&lt;/tt&gt; with &lt;tt&gt;OutFwd(OUT_B, ...)&lt;/tt&gt; and &lt;tt&gt;OutFwd(OUT_C, ...)&lt;/tt&gt; (with power values based on whether we think we should be turning right or left), the jerkiness problem was solved.&lt;br /&gt;&lt;br /&gt;I also used their idea of calibrating the sensor at the beginning (the robot rotates a bit to the left and then to the right, noting the maximum and minimum light levels and chooses the threshold value as the average of the two).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/xF9CUUQMRe2TbqiUVUX1Nw?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_5TvSUp77d78/TG6Uo9ATG-I/AAAAAAAABrs/JJ0gbdWAidc/s400/IMG_20100820_164034.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You will note that I used a faster version of the program for the NXT Test Pad and a slower version for following the line that I made on the floor with electrical tape. I had to do this because the robot kept losing the line (probably because the tape was too narrow, it was also blue, not black, and some of the turns I made may have been too sharp).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-4651282954425393496?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/08/line-following-robot.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/7XL83VGEYjU/default.jpg' height='72' width='72'/><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-5539287429040269392</guid><pubDate>Tue, 17 Aug 2010 16:54:00 +0000</pubDate><atom:updated>2010-08-17T18:54:39.416+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>Music Tape Player</title><description>My second NXT creation is a music player that uses the color sensor to read notes from tape.&lt;br /&gt;&lt;br /&gt;&lt;iframe class="youtube-player" type="text/html" width="480" height="385" src="http://www.youtube.com/embed/1MNcMi80ri8?hl=en_US" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;The notes are encoded using colors. I considered using shades of gray and then using the color sensor in light level mode to read them, but that would require calibration (as the readouts would be dependent on current light conditions in the room) and possibly wouldn't allow for more than 5 or 6 well-distinguishable levels anyway.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/0iT_x-8h8gbBc_Mr22-yPg?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_5TvSUp77d78/TGq3uyT_i8I/AAAAAAAABpc/iwjK5rNSMzo/s400/IMG_20100817_180707.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's the &lt;a href="http://www.jfedor.org/lego/tape0.nxc"&gt;NXC program&lt;/a&gt; that the device is running. As you can see it constantly reads the color sensor and adjusts the sound accordingly. Another way of doing this would be to only read the color at certain intervals, which would eliminate the problem that sometimes occurs when the color sensor gets confused during the transition between one color and another. But the current approach has the nice feature that we can have notes of arbitrary lengths (by simply putting a wider or less wide stripe of color on the tape). It also doesn't require any synchronization.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/nhgCBMMcjW3jPImb5V_PNA?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_5TvSUp77d78/TGq3mY2wLWI/AAAAAAAABpc/cK2deVHrc1o/s400/IMG_20100817_180757.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Possible improvements might include:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;an encoding scheme that would allow for more than five notes&lt;/li&gt;&lt;li&gt;a mechanism for stopping the tape at the end&lt;/li&gt;&lt;li&gt;a rewinding mechanism&lt;/li&gt;&lt;li&gt;a better tune for demonstration&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/lWwNPSTdA8XU7_qoxP9QOA?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_5TvSUp77d78/TGq3qQ5ddqI/AAAAAAAABpc/n8R7IkTU6XE/s400/IMG_20100817_180730.jpg" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-5539287429040269392?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/08/music-tape-player.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/1MNcMi80ri8/default.jpg' height='72' width='72'/><thr:total>4</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-2275915117471914676</guid><pubDate>Thu, 12 Aug 2010 17:29:00 +0000</pubDate><atom:updated>2010-08-13T00:56:46.702+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lego</category><category domain='http://www.blogger.com/atom/ns#'>nxt</category><title>Sonar</title><description>This is my first Mindstorms robot. It rotates around the vertical axis while gathering data from the ultrasonic sensor. Every time it makes a full circle it plots the gathered data on the display. The results are mixed.&lt;br /&gt;&lt;br /&gt;&lt;iframe class="youtube-player" type="text/html" width="480" height="385" src="http://www.youtube.com/embed/KBhgJXQSCbw?hl=en_US" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Can you guess what the red ball is for?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/1-Lz0fPb3TnJDHMzAmgzGg?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_5TvSUp77d78/TGQl6nNRy4I/AAAAAAAABoI/UyaI6UqKmZo/s400/IMG_20100812_184335.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/Z0ZzbAHSW_jCOn5NhKkEWg?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_5TvSUp77d78/TGQlw8AG8AI/AAAAAAAABoI/oem-9SkI91o/s400/IMG_20100812_183830.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;OK, so the red ball is there so that the robot knows it made a full circle. You can see that the color sensor rotates with the rest of the robot while the ball remains still.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/ZLhLYUdwAzjOI3qGEbIoQw?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_5TvSUp77d78/TGQlqsdlAfI/AAAAAAAABoI/_oEbMV80Rgg/s400/IMG_20100812_183728.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's the &lt;a href="http://www.jfedor.org/lego/sonar.nxc"&gt;source code&lt;/a&gt; for the program that the robot is running.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-2275915117471914676?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/08/sonar.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/KBhgJXQSCbw/default.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5743520447405866726.post-5387666196331132964</guid><pubDate>Thu, 12 Aug 2010 16:59:00 +0000</pubDate><atom:updated>2010-08-12T18:59:51.808+02:00</atom:updated><title>Hello</title><description>Yeah, hi. This is my blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5743520447405866726-5387666196331132964?l=blog.jfedor.org' alt='' /&gt;&lt;/div&gt;</description><link>http://blog.jfedor.org/2010/08/hello.html</link><author>noreply@blogger.com (Jacek Fedoryński)</author><thr:total>1</thr:total></item></channel></rss>
