About Me

My Photo

I previously worked on Virtual Reality and other hardware at Valve.  I currently work at Google[x].

Prior to starting at Valve, I built computer peripherals such as keyboards, mice, and joysticks that were designed to be used inside MRI machines.  My company, Mag Design and Engineering, sold these devices directly to researchers at academic institutions who used them to publish scientific papers in peer-reviewed journals.

After work, I spend time on many different types of projects that usually involve circuit design, machining, material selection, and general fabrication/hacking.  My favorite place to be is my home workshop.

ben dot krasnow at gmail

http://www.youtube.com/user/bkraz333

http://www.linkedin.com/pub/ben-krasnow/4/6a9/679

http://www.twitter.com/BenKrasnow

Friday, December 25, 2009

Using my hacked espresso machine

I recently bought a Saeco Titan coffee grinder, and have been very pleased with the consistency and control of the grind size. I had to hack it (of course) to get the grind fine enough for espresso, but it's working, and it seems like a well-built machine.
For info on adjusting the grind size outside of the factory settings, see here:
http://www.ineedcoffee.com/07/hack-starbucks-grinder/
The Saeco Titan, Starbucks Barista, and Solis 166 are all the same machine. There are probably a few other rebranded models out there too.


A few years ago, I took a Krups "steam-powered" espresso machine and retrofitted it with a temperature control and air pump. The air pump pressurizes the air above the hot water in the heating tank, and the water is conveyed from the bottom of the tank to the group head. Thus, the air pressure will be the same as the water pressure. This differs from commercial espresso machines which use a water pump to move a specific volume of water through the coffee. The pressure is determined by the resistance the coffee poses to the set flow rate of water.


The temperature control was hacked from an old meat thermometer. It has a very basic proportional control. The air pump was salvaged from a 12V tire-inflator compressor. The large circuit board is a computer power supply that provides high current 12V to the compressor.

About 14g of coffee, finely ground and tamped down into the portafilter.

http://www.youtube.com/watch?v=WfhszeLt40k

I realize my shot is a little fast and pours out too violently. I'm still figuring out the ideal pressures and valve opening sequences for this machine. Since this is essentially a constant-pressure machine and commerical machines are constant flow-rate, there may always be some differences in how the coffee is made.

Lots of crema. This demitasse holds about 2 oz with additional headroom for the crema. It tastes great! I am very happy with the espresso that it makes. On cold days, I usually take a sip from the demitasse, then dump the rest into a large mug of hot water for an Americano.

Wednesday, December 23, 2009

Fixing file permissions in Vista

I downloaded some MP3 files from lala.com, and put them into my shared music folder on a Vista computer. Surprisingly, they didn't appear in my music player when I connected to the Vista machine with a client Windows XP machine. I could see all the other MP3 in the folder, but not the files from lala.com. I right-clicked on a working file and compared the file permissions to a non-working file. Sure enough, the non-working file was missing permissions for "authenticated users". I guess the lala app normally creates files with restrictive permissions. Windows explorer, when making a copy, will make files that are readable through Windows file sharing. I tried to fix the permissions through Vista's dialog boxes -- a hugely complicated and difficult process.

Instead, I found this:
icacls c:\ben\music /grant "Authenticated Users":F /t

This fixed all files in one command!

You can run icacls all by itself to see its usage.

Sunday, December 20, 2009

Making bowls from vinyl records (LPs)

I've seen pictures of bowls made from vinyl records, and decided to try it myself. I have a colander and a stainless bowl that fit together pretty tightly, which is what I used to mold the records. I put one record at a time in the oven for a few minutes at 200*F. After the vinyl had softened, I put the record into the colander and forced the bowl down on top.



The record cools in a few seconds.Neat! I think the next thing I would try is vacuum-forming. It would probably leave a much more attractive finish with fewer if any folds and overlapping sections.

Saturday, December 19, 2009

Bluetooth AVRCP failure

I learned that the mysterious behavior of the AVRCP (audio/video remote control protocol) failure on my HTC G1 is actually systematic and repeatable. If the phone is sleeping when the Bluetooth device is powered on, AVRCP will not be setup correctly. However, if the phone is awake, the connection will proceed perfectly. Here is a side-by-side comparison of the logs for a successful setup (left) and a failure (right):
It appears that the failure occurs because the phone doesn't initiate the A2DP connection. Note the time differences between the "AT sent OK" and "Auto-connecting A2DP" for each scenario. I have posted this on the Cyanogenmod issues tracker:
http://code.google.com/p/cyanogenmod/issues/detail?id=611

I've also been looking through the Cyanogen code, but I haven't noticed anything yet that would cause the device's behavior to change based on whether it is sleeping or not.

Wednesday, December 9, 2009

More bluetooth a2dp debugging on Android Cyanogen

There are a few different failure modes that I have encountered, however these are the most obvious and annoying one:

12-09 17:56:53.949 D/BluetoothA2dpService( 944): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 0->1

12-09 17:57:01.453 E/BluetoothA2dpService.cpp( 944): onConnectSinkResult: D-Bus error: org.bluez.Error.Failed (Stream setup failed)
12-09 17:57:03.469 D/BluetoothA2dpService( 944): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 1->0




:10:40.214 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 0->1
12-11 18:10:40.214 E/BluetoothA2dpService.cpp( 99): onConnectSinkResult: D-Bus error: org.bluez.Error.Failed (%s)

12-11 18:10:50.574 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 1->0







12-22 14:48:39.111 D/AudioFlinger( 78): set output to A2DP
12-22 14:48:39.121 D/BluetoothA2dpService( 94): state 00:02:76:64:F7:4A (/org/bluez/audio/device0) 1->2
12-22 14:48:40.321 W/KeyCharacterMap( 148): Can't open keycharmap file
12-22 14:48:40.321 W/KeyCharacterMap( 148): Error loading keycharmap file '/system/usr/keychars/AVRCP.kcm.bin'. hw.keyboards.262149.devname='AVRCP'
12-22 14:48:40.321 W/KeyCharacterMap( 148): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
12-22 14:48:40.391 W/Service ( 963): setForeground: ignoring old API call on com.android.music.MediaPlaybackService
12-22 14:48:41.403 W/AudioTrack( 78): obtainBuffer timed out (is the CPU pegged?) 0x58dd0 user=010c3b70, server=010c1370
12-22 14:48:41.403 E/A2dpAudioInterface( 78): a2dp_write failed err: -110
12-22 14:48:41.411 W/AudioFlinger( 78): write blocked for 1010 msecs
12-22 14:48:42.411 W/AudioTrack( 78): obtainBuffer timed out (is the CPU pegged?) 0x58dd0 user=010c4570, server=010c1d70
12-22 14:48:42.411 E/A2dpAudioInterface( 78): a2dp_write failed err: -110
12-22 14:48:42.421 W/AudioFlinger( 78): write blocked for 1010 msecs
12-22 14:48:43.431 W/AudioTrack( 78): obtainBuffer timed out (is the CPU pegged?) 0x58dd0 user=010c4f70, server=010c2770
12-22 14:48:43.431 E/A2dpAudioInterface( 78): a2dp_write failed err: -110
12-22 14:48:43.451 W/AudioFlinger( 78): write blocked for 1021 msecs
12-22 14:48:44.452 W/AudioTrack( 78): obtainBuffer timed out (is the CPU pegged?) 0x58dd0 user=010c5970, server=010c3170
12-22 14:48:44.462 E/A2dpAudioInterface( 78): a2dp_write failed err: -110
12-22 14:48:44.472 W/AudioFlinger( 78): write blocked for 1010 msecs
12-22 14:48:45.472 W/AudioTrack( 78): obtainBuffer timed out (is the CPU pegged?) 0x58dd0 user=010c6370, server=010c3b70
12-22 14:48:45.472 E/A2dpAudioInterface( 78): a2dp_write failed err: -110
12-22 14:48:45.482 W/AudioFlinger( 78): write blocked for 1009 msecs
12-22 14:48:45.721 D/dalvikvm( 938): GC freed 842 objects / 41408 bytes in 124ms
12-22 14:48:46.484 W/AudioTrack( 78): obtainBuffer timed out (is the CPU pegged?) 0x58dd0 user=010c6d70, server=010c4570

Debugging Bluetooth A2DP on Cyanogen G1

UPDATE: The connection problem turns out to be related to AVRCP, not A2DP. For some reason, the phone will connect to the A2DP device perfectly (with AVRCP) if the phone is awake when the A2DP device is powered on. If the phone is sleeping when the A2DP device is powered on, the connection process is different and AVRCP is lost. A2DP will be connected, though.

See this thread:
http://code.google.com/p/cyanogenmod/issues/detail?id=611



So, I'm still having problems with getting a reliable AVRCP and A2DP connection with Cyanogenmod 4.2.7.1 on my G1.

Here is a log from a successful connection:
12-09 09:52:36.660 I/BT Audio Gateway( 150): connect notification!
[[[ Setting up phone audio connection ]]]
12-09 09:52:41.730 D/BluetoothA2dpService( 99): Auto-connecting A2DP to sink 00:02:76:64:F7:4A
12-09 09:52:41.730 D/BluetoothA2dpService( 99): connectSink(00:02:76:64:F7:4A)
12-09 09:52:41.750 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 0->1
12-09 09:52:42.220 I/CheckinService( 99): Checkin success
12-09 09:52:42.280 W/GoogleHttpClient( 99): Blocked by block_crash_reports: http://android.clients.google.com/crash
12-09 09:52:42.280 I/CheckinService( 99): Crash report blocked
12-09 09:52:46.276 I/EventHub( 99): New device: path=/dev/input/event5 name=AVRCP id=0x10005 (of 0x6) index=6 fd=118 classes=0x1
12-09 09:52:46.286 I/EventHub( 99): New keyboard: publicID=65541 device->id=65541 devname='AVRCP' propName='hw.keyboards.65541.devname' keylayout='/system/usr/keylayout/AVRCP.kl'
12-09 09:52:46.286 I/KeyInputQueue( 99): Device added: id=0x10005, name=AVRCP, classes=1
12-09 09:52:46.286 I/WindowManager( 99): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=2/1/2 nav=3 orien=1 layout=18}
12-09 09:52:46.946 D/A2dpAudioInterface( 83): setParameter a2dp_sink_address,00:02:76:64:F7:4A
12-09 09:52:46.965 D/AudioFlinger( 83): set output to A2DP
12-09 09:52:46.975 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 1->2
12-09 09:53:07.738 D/dalvikvm( 99): GC freed 18113 objects / 1104992 bytes in 206ms
12-09 09:53:07.798 D/OpenSSLSessionImpl( 99): Freeing OpenSSL session
12-09 09:53:07.948 I/ActivityManager( 99): Start proc com.android.music for broadcast com.android.music/.MediaButtonIntentReceiver: pid=1803 uid=10017 gids={3002, 3001, 3003, 1015}
12-09 09:53:07.948 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498 1803:com.android.music/10017}
12-09 09:53:07.988 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498 1803:com.android.music/10017}
12-09 09:53:08.038 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498 1803:com.android.music/10017}
12-09 09:53:08.068 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498 1803:com.android.music/10017}
12-09 09:53:09.108 D/A2DP ( 83): bluetooth_start
12-09 09:53:09.108 E/A2DP ( 83): BT_START failed : I/O error(5)
12-09 09:53:09.108 D/A2DP ( 83): bluetooth_configure
12-09 09:53:09.108 D/A2DP ( 83): bluetooth_a2dp_hw_params sending configuration:
12-09 09:53:09.108 D/A2DP ( 83): channel_mode: JOINT STEREO
12-09 09:53:09.108 D/A2DP ( 83): frequency: 44100
12-09 09:53:09.108 D/A2DP ( 83): allocation_method: LOUDNESS
12-09 09:53:09.108 D/A2DP ( 83): subbands: 8
12-09 09:53:09.108 D/A2DP ( 83): block_length: 16
12-09 09:53:09.108 D/A2DP ( 83): min_bitpool: 2
12-09 09:53:09.108 D/A2DP ( 83): max_bitpool: 32
12-09 09:53:09.118 D/A2DP ( 83): MTU: 895
12-09 09:53:09.118 D/A2DP ( 83): frame_duration: 2902 us
12-09 09:53:09.118 D/A2DP ( 83): allocation=0
12-09 09:53:09.118 D/A2DP ( 83): subbands=1
12-09 09:53:09.118 D/A2DP ( 83): blocks=3
12-09 09:53:09.118 D/A2DP ( 83): bitpool=32
12-09 09:53:09.118 D/A2DP ( 83): bluetooth_start
12-09 09:53:09.168 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 2->4
12-09 09:53:13.505 D/KeyguardViewMediator( 99): wakeWhenReadyLocked(82)
12-09 09:53:13.505 D/KeyguardViewMediator( 99): handleWakeWhenReady(82)
12-09 09:53:13.515 D/KeyguardViewMediator( 99): pokeWakelock(5000)
12-09 09:53:13.535 D/Sensors ( 99): sensors=00000001, real=00000001
12-09 09:53:13.535 D/AKMD ( 88): Compass OPEN
12-09 09:53:13.695 I/Bluetooth AT sent( 150): +CIEV: 5,5
12-09 09:53:13.765 D/SurfaceFlinger( 99): Screen about to return, flinger = 0xff388
12-09 09:53:14.455 D/KeyguardViewMediator( 99): pokeWakelock(5000)
12-09 09:53:15.795 D/A2DP ( 83): a2dp_stop
12-09 09:53:15.795 D/A2DP ( 83): bluetooth_stop
12-09 09:53:15.855 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 4->2




Here is the log from a connect-then-disconnect-then-reconnect (without AVRCP)
12-08 15:57:02.213 D/BluetoothA2dpService( 99): Auto-connecting A2DP to sink 00:02:76:64:F7:4A
12-08 15:57:02.213 D/BluetoothA2dpService( 99): connectSink(00:02:76:64:F7:4A)
12-08 15:57:02.223 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 0->1
12-08 15:57:02.553 I/ActivityManager( 99): Stopping service: com.android.calendar/.AlertService
12-08 15:57:02.593 I/ActivityManager( 99): Stopping service: com.android.mms/.transaction.SmsReceiverService
12-08 15:57:02.733 E/BluetoothA2dpService.cpp( 99): onConnectSinkResult: D-Bus error: org.bluez.Error.Failed (Stream setup failed)
12-08 15:57:03.393 I/BluetoothEventLoop( 99): Allowing incoming A2DP connection from 00:02:76:64:F7:4A
12-08 15:57:04.753 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 1->0
12-08 15:57:09.658 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 0->1
12-08 15:57:09.658 D/A2dpAudioInterface( 83): setParameter a2dp_sink_address,00:02:76:64:F7:4A
12-08 15:57:09.668 D/AudioFlinger( 83): set output to A2DP
12-08 15:57:09.718 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 1->2


Disabled phone audio, and now only have A2DP connection. AVRCP looks fine in log, but doesn't work at all:
12-09 09:57:51.661 I/BluetoothEventLoop( 99): Allowing incoming A2DP connection from 00:02:76:64:F7:4A
12-09 09:57:54.331 I/EventHub( 99): New device: path=/dev/input/event5 name=AVRCP id=0x10005 (of 0x6) index=6 fd=31 classes=0x1
12-09 09:57:54.341 I/EventHub( 99): New keyboard: publicID=65541 device->id=65541 devname='AVRCP' propName='hw.keyboards.65541.devname' keylayout='/system/usr/keylayout/AVRCP.kl'
12-09 09:57:54.341 I/KeyInputQueue( 99): Device added: id=0x10005, name=AVRCP, classes=1
12-09 09:57:54.351 I/WindowManager( 99): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=2/1/2 nav=3 orien=1 layout=18}
12-09 09:57:54.551 D/dalvikvm( 99): GC freed 7743 objects / 388840 bytes in 208ms
12-09 09:57:58.261 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 0->1
12-09 09:57:58.371 D/A2dpAudioInterface( 83): setParameter a2dp_sink_address,00:02:76:64:F7:4A
12-09 09:57:58.381 D/A2DP ( 83): bluetooth_init
12-09 09:57:58.391 D/A2DP ( 83): bluetooth_configure
12-09 09:57:58.391 D/A2DP ( 83): bluetooth_a2dp_hw_params sending configuration:
12-09 09:57:58.391 D/A2DP ( 83): channel_mode: JOINT STEREO
12-09 09:57:58.391 D/A2DP ( 83): frequency: 44100
12-09 09:57:58.391 D/A2DP ( 83): allocation_method: LOUDNESS
12-09 09:57:58.391 D/A2DP ( 83): subbands: 8
12-09 09:57:58.391 D/A2DP ( 83): block_length: 16
12-09 09:57:58.391 D/A2DP ( 83): min_bitpool: 2
12-09 09:57:58.391 D/A2DP ( 83): max_bitpool: 32
12-09 09:57:58.421 D/A2DP ( 83): MTU: 895
12-09 09:57:58.421 D/A2DP ( 83): frame_duration: 2902 us
12-09 09:57:58.421 D/A2DP ( 83): allocation=0
12-09 09:57:58.421 D/A2DP ( 83): subbands=1
12-09 09:57:58.421 D/A2DP ( 83): blocks=3
12-09 09:57:58.421 D/A2DP ( 83): bitpool=32
12-09 09:57:58.421 D/AudioFlinger( 83): set output to A2DP
12-09 09:57:58.431 D/BluetoothA2dpService( 99): state 00:02:76:64:F7:4A (/org/bluez/audio/device1) 1->2

Friday, December 4, 2009

Installing Bluetooth audio in my car with a Motorola s705 Pt.2

After about two weeks of life with the Bluetooth audio system in my car, I'd say it has reached about %80 of its design expectations, and with a little tweaking, might be made perfect.

The #1 gripe: When the Motorola S705 is powered on (after I've started the car), the phone audio connects, immediately disconnects, then reconnects. In the process, the AVRCP protocol for remote-controlling the media player on the phone is lost. This means that I have to take the phone out of my pocket, load up the media player, then hit play. I know, it sounds like a really minor complaint, but the system would be a whole lot more enjoyable if I could just press a button on the dash and not fumble with the phone at all.

In order to fix this problem, I've installed the latest Cyanogen ROM. I've noticed a few threads that discuss A2DP and AVRCP reliability problems with android in general:
http://code.google.com/p/cyanogenmod/issues/detail?id=360
http://code.google.com/p/cyanogenmod/issues/detail?id=611

Both issues have been closed, but one person commented that he/she is still having problems with 4.2.1 after the issue was closed.

Today, I installed 4.2.7.1. I hopped in the car and was disappointed to see the same problem (loss of AVRCP after a botched connection). I hooked up the phone to my computer and ran ADB logcat to see if I could get more info about the error. After 30 power-off/power-on cycles, the Bluetooth connection was always established perfectly with AVRCP. Geez! Obviously, I don't know if it's really fixed or not.


I decided that I will sync the phone with my music collection via USB. Originally, I thought it would be cool to do it wirelessly and automatically, but it turned out to be very easy to just plug it in and sync with MediaMonkey. The program chooses a random selection from my music collection and fills the phone's SD card up to capacity. I sync about once per week.

The automatic power-on and power-off circuitry to control the Motorola S705 works perfectly.

Also, the audio quality is good, but not quite as great as I originally thought. It's true that bass and treble are not attenuated, but there are noticeable compression artifacts in the sound that are not present in the source MP3. Cymbals sound kind of fuzzy, scratchy-- like the sound is coming from under water. It's not bad, but it's probably not quite as good as a 128-bit MP3. It's still fine enough for listening in the car where road noise is present.

More later...