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:
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.

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, 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 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:

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
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:

So, I'm still having problems with getting a reliable AVRCP and A2DP connection with Cyanogenmod 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:
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 for broadcast pid=1803 uid=10017 gids={3002, 3001, 3003, 1015}
12-09 09:53:07.948 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498}
12-09 09:53:07.988 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498}
12-09 09:53:08.038 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498}
12-09 09:53:08.068 I/ActivityManager( 99): processNextBroadcast: waiting for ProcessRecord{43e9d498}
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:
12-08 15:57:02.593 I/ActivityManager( 99): Stopping service:
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:

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 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...

Saturday, November 21, 2009

Stainless steel conical beer fermenter Pt.8

The beer fermenter project is finally ready for its first batch of beer. I bought a soft silicone strip from McMaster and cut a scarf joint in it. The diameter of the finished ring matches the lid on the fermenter.

I did some testing and verified that standard silicone adhesive would bond the red silicone rubber strip very well. I am pretty sure that if tested to destruction, the glue joint would break before the rubber itself would, but it still seems tough enough for this application.

I also welded my stainless cooling coil into the lid.

I made some Delrin clamps to keep the lid held tightly onto the tank. The silicone rubber is very soft which helps easily make a seal with minimal clamping pressure. I clamped it all up, shut both valves, and sucked some air out with my lungs. I could feel the vessel holding the vacuum that I created, so I assume the setup is essentially air-tight.

OK, so now it's time to brew some beer! Any recipe suggestions?

Friday, November 20, 2009

Installing Bluetooth audio in my car with a Motorola s705

I am nearly done with my project to create a seamless way of playing music that is stored on my computer in my car. I bought a Motorola s705, which is a Bluetooth audio receiver with headphone jack. It is capable of operating as a standard phone headset and also capable of receiving high-quality audio. First, let me review the s705 itself:

I easily paired the s705 with my HTC G1, and was able to play music through the s705 with no trouble. The sound quality was extremely good -- significantly better than the G1's own headphone adapter. It appears the high-pass filtering that the G1 uses on its own audio stream are thankfully not also used on the bluetooth high-quality audio stream. I could not hear any compression artifacts, and the sound quality remained top-notch as I walked up to about 15 feet away from the phone. I did not test the s705's battery life. I accidentally turned on the FM radio a few times, and I wish that feature could be disabled. The only negative thing is that the s705 and G1 sometimes do not connect to each other after being separated, then brought back together. Sometimes, they will only establish a phone audio connection and not a high-quality (A2DP) connection. Turning the phone off and on (or going into airplane mode and back) always fixes the problem. Turning the s705 off and on sometimes fixes the problem.

So after I decided the s705 would probably do the job, I took it apart (of course). I needed a way to remotely control the s705 power (to have it turn on everytime I started the car, and off when I shut car off), and also a way to allow it to charge its own battery while not running the car battery down.

In order to turn the s705 on or off, the power switch must be held down for three seconds. One side of the power switch would go high (about 4 volts) when the switch was pressed. Thus, I could control the device's power state by sending it a 4 volt pulse that lasted three seconds. My first plan was to use an Atmel AVR microcontroller and use a feedback circuit so that the AVR would know whether the unit was on or off. I had difficulty finding a reliable logic signal on the s705 circuit board that could be used as an on/off indicator. I was also having difficulty with the Atmel IDE that night, so I scrapped it, and decided to use two basic timer circuits (a 555 and 558 chip). The circuits send a pulse when the car turns on, and another pulse when the car turns off. It's possible for the device to become out of sync, but I don't think it will happen. The circuit uses a MOSFET whose gate is driven by a capacitor-resistor network and charged by the "on" signal from the car stereo. This way, the device will draw essentially zero current after the gate discharges and the MOSFET turns off. I've configured the capacitor value so that the circuit stays powered for 15 seconds after the car turns off.

I also wanted to sneak the audio wires out the back of the unit instead of using the headphone jack on top. I figured this would look a lot nicer when I mounted the unit on my car's dashboard.

I used the s705 shirt clip to attach it to an unused switch plate in my 1992 Honda Civic. It fits right next to the rear defroster switch.

The row of header pins have the following signals:
1. gnd
2. +12V always on from the battery
3. +5V signal from car stereo when the aux input is active
4. audio signal gnd
5. audio left
6. audio right

The audio connections go to my car stereo "aux input" which I described in another post:

The shirt clip was ABS plastic as was the switch dummy plate. I used some Weld-On #16 glue which will very securely bond ABS plastic.

It's a pretty clean installation. I've just finished it, and I'll let everyone know how it works in day-to-day use. So far, my tests in the driveway have been really great -- just step into the car and turn on the stereo, hit play on the s705, and the music starts. I don't even have to take the phone out of my pocket.

Thursday, November 19, 2009

Adhesive for polypropylene and other low-energy surface plastics

I recently had the task of gluing two pieces of polypropylene plastic together. It sounds easy, but polypropylene is a plastic with very low "surface energy" -- meaning it's difficult for most adhesives to "wet" the surface and make a good bond.

This problem of not being able to wet the surface can be seen when dripping water on a recently waxed car. The water forms beads and quickly rolls off the surface. If the car's surface has not been waxed in a long time, the water droplet may stick to the surface and form a sheet or stream of water flowing on the surface. The difference is that the wax provides a much lower energy surface to the water, which has a difficult time sticking to the wax and forms a bead and rolls away.

Plastics with low surface energy (polypropylene, polyethylene, etc) are used for food containers and other vessels because of their mechanical properties and also their inert surface that allows liquids to easily roll off. So, how to glue them? I searched the web and found this product:

3M Scotch-Weld DP8005. It has some magical composition that allows it to wet very low energy surfaces.

It's pretty expensive -- a little over $20 at McMaster, plus the special plunger (another $8). The tube of adhesive and plunger are intended to be used in a dispenser that works like a caulk gun. They also sell a mixing tip that swirls the two parts of the adhesive before dispensing. That's all fine, but I prefer to just mix with a nail on a piece of paper. I bought only the tube and plunger and had no difficulty dispensing, mixing then applying with a nail.

The adhesive itself is pretty weird. It's gritty, like it contains tiny glass beads or sand. I applied the adhesive to my project (polypropylene bottle and flat slab of polypropylene), and put the pieces with very light clamping pressure in an oven at about 80*F for about six hours. I shut off the oven and went to bed. The overnight temperature in my shop was probably 50*F.

The next day, I took the parts out of the oven and was glad to see the adhesive worked very well. It made a very strong bond -- strong enough for me to drill and tap two holes with 1/8" pipe threads in the 1/4" thick slab that I glued to the bottle. The plastic showed no signs of coming loose. I made six bottles like this, but didn't have a spare bottle for destructive testing.

Wednesday, November 11, 2009

DIY aux input cable for Kenwood car stereos

In order to achieve my master plan of abandoning CDs and converting entirely to digital/wireless music, I need to get an audio stream into my car stereo. It is a Kenwood kdc-mpv619. The front of the stereo has no input jacks. The back has output RCA plugs, but no inputs. The only way to get a signal into the stereo is to use the CD-changer connector. This is a 13-pin DIN connector that contains pins for the audio signals as well as CD changer control signals. Around the year 2001, Kenwood realized that people wanted to use the connector for aux input and started to sell an adapter ( CA-C1AUX ) to convert the 13-pin DIN into a pair of RCA input jacks. Prior to 2001, Kenwood models would not accept audio on the DIN connector until it had established digital communication with the CD changer. I know this because I had to get a CD changer and hi-jack the audio lines for an older Kenwood stereo that I have. Anyway I made a copy of the C1AUX adapter, and also helped myself to the power lines that are supplied in the DIN connector.

The resistor is necessary to indicate that there is something connected, and that the stereo should make "aux" available in its menu of input selections.

So, it all worked fine, but the sound on the G1 was still horrible. No bass. No treble, but there didn't seem to be much distortion. It actually sounded pretty clean.

The next step will be to use a bluetooth receiver to feed audio into the car stereo.

Making twisted wiring harnesses with a hand drill

My dad learned this trick from a stereo installer when he worked at a Honda dealership. If you use similarly-sized wires, the resulting twist pattern is very uniform and professional-looking. Cut off a bunch of pieces of wire, then stuff all of the ends into a the drill chuck and clamp it down. Start the drill turning, and use your other hand to keep tension on the wires.

In this case, I made a wiring harness with a stereo audio cable and two power conductors.

Tuesday, November 10, 2009

Rooting and modding an HTC Dream (Google G1)

This project all started with my plan to abandon music CDs and use my G1 phone to carry all of my music. Here's how my ideal situation would work: When I get in my car, I would like to press a button and hear a series of random songs from my music collection that is stored on my computer. Note that I didn't say anything about connecting wires, syncing, downloading, looking through settings or album lists, etc. In the ideal plan, the music would all be handled seamlessly without any thought on my mind except "play".

By the way, I have been using MediaMonkey to handle my music, and I really like it:

The G1 is a very flexible device, so I figured this would be no problem. However, there are problems. First, the audio quality coming out of the usb->headphone jack adapter on the G1 is truly dreadful. I am not being a stuck-up about this. I mean it's just plain bad. The sound has no bass (it seems anything below 150Hz is completely gone). There are a lot of compression artifacts evident in cymbal sounds, and the high-mids are unusually harsh-sounding. Finally, the overall amount of signal coming out of the headphone jack is very low. Before anyone accuses me of using low-quality MP3, let me say that I made these MP3 myself from CDs and used 320kbit for some test files. They are good MP3 and sound perfectly fine on normal sound systems.

So, connecting the G1 to my car's sound system via a headphone jack, while slightly inconvenient may not work at all because of the low quality. This prompted me to wonder if the Android software had any control over the sound output. As a matter of fact. It does, and it's possible the designers purposefully cut everything below 150Hz for use with speech-only audio.
Ah, nothing like a 120-page thread. I'm sure it will only take a few hours to read it.

Anyway, the short story is that a developer named meltus has found three audio files in the system/etc directory of the android operating system that have some effect on the sound processing. I was intrigued and wanted to edit the files myself to see how much of the audio quality was dependent upon software. Unfortunately, the android system will not allow anyone to edit system files (even me, the owner of the damn phone). I instantly decided to "root" the phone so that I could investigate the full potential of the device.

Gaining root access is possible on the G1 by a few different ways, but the information available on the web is sketchy. There are only two groups of people who root their phones: 1. Serious developers who are so into Android, that they don't have time to explain the process to newbies 2. Newbies who want root access but don't know what it is. There is a major echo chamber on the web just filled with mindless stupid comments from people hacking away at their phones. I am not against hacking, I am only against repeating misinformation in forums and wasting bandwidth by repeating hearsay over and over again.

Anyway, I followed Cyanogen's instructions, and didn't have any problems at all:
This guy deserves major props for writing a clear, concise set of directions.

The process of downgrading to RC29 is not that hard, and the whole process took less than an hour.

So, here it is, and I know have complete control of my own phone.

The next steps will be to see how much better the audio quality can be made, testing bluetooth high-quality audio, syncing MP3 over Wifi, installing a bluetooth receiver in the car, etc.

Saturday, November 7, 2009

Improved level sensor for the DIY aquarium top-off project

In my
original post regarding an automatic water top-off system for aquariums, I designed a sensor head that consisted of a plastic rod with a set of pocket holes drilled at the tip. The holes were diametrically opposed and angled so that they intersected at a point about 1cm in front of the plastic rod face. I inserted a plastic fiberoptic into each of the holes, and the system would allow sensing a liquid level surface by measuring the amount of light reflected off the surface. If the liquid covered the two probes, all of the light would be scattered off into the liquid and the signal would be almost zero. When the level fell below the fiber ends, the reflected light would trigger the top-off pump.

This system worked very well until nearly flooding my house a couple weeks ago. By extreme luck, I happened to be sitting near the aquarium when an air bubble got trapped between the two fiberoptic ends. This caused the top-off pump to run even after the water level had risen higher than the sensor head. I heard the tank dripping water and quickly shut off the pump. Following this event, I decided to improve the reliability of the sensor.

I did some searching for commercially-built liquid level sensors and found that many of them operate by submerging a prism and measuring the amount of total internal reflection. When the prism is submerged in liquid, the light will pass out of the prism and into the liquid. When dry, the prism will reflect most of the light internally. By positioning the fiberoptics symmetrically, the light signal will be drastically changed by the liquid surrounding the prism.

I machined and polished a piece of acrylic into a point. Then I drilled two holes that would snugly hold the fiberoptics. I mounted the whole thing on a Delrin rod.

This sensor should be much less sensitive to air bubbles, snails, dirt, etc than the previous model. For the next week, I'll be monitoring the top-off system and manually controlling the pump. If it looks good, I will connect the pump and let everyone know how it works.

Monday, November 2, 2009

Drinking glass carrier

This project was inspired by a brew-pub in San Francisco called the Beach Chalet. They have a "beer sampler" on their menu that includes small portions of six of their beers. The beers are served in small glasses that fit into a wooden rack. Neat!

It's been a while since I have been to the Beach Chalet, so I don't remember their wooden sampler rack in detail. That's just as well, since I wanted to design my own anyway. I used maple, walnut, and bloodwood (the same woods that I always use) in this project. The central brass rod is threaded from its midpoint to the bottom and it passes all the way through the wood top and base. A brass nut and washer clamp the top of the rack and another washer and nut are located under the base. The set of nuts clamp the top to the base with no danger of a glue joint breaking (the end-grain to side-grain glue joints aren't very reliable). The brass rod has a hole drilled through it near the top, and a small brass ring is mounted in it for easy carrying. The ring was sealed shut with silver solder.

Saturday, October 31, 2009

Halloween prop: monster in a box

Every Halloween, my dad and I put together a small haunted house on the porch of his house. Most of the props are remotely controlled lights, sound effects, etc. This year, I made a new prop that was inspired by something I saw at this year's Maker Faire. It's a wooden crate with a pneumatic cylinder mounted on the inside facing toward the ground. When the cylinder is filled with air, it violently lifts the crate up an inch or two. When the air pressure is released, the crate comes crashing back down to the ground. I also put a heavy chain on top of the crate for a great visual and audible effect. There is a colored light bulb inside the crate that is illuminated at the same instant the gas cylinder is filled.

The wooden crate came from Michaels craft store ($10), and the chain was from Home Depot. I used the chain previously with a come-along winch and had it in my garage already.

I am using a 5# CO2 tank to supply gas pressure to the valve at about 100 psi. The valve is a Clippard Maximatic 12VDC, direct-acting 3-way valve.

Thursday, October 22, 2009

Stainless steel conical beer fermenter Pt.7

The conical fermenter project is coming along well. Here is what's left to do:
1. Mount stainless cooling coil (chiller) to bottom of lid so that I can quickly chill the hot wort after boiling.

2. Make a silicone seal for the lid

3. Make some beer! Wow, I can't believe this project is almost done... it's taken a long time.

Here's a picture of the lid with a thermowell that I made. The thermowell allows a temperature probe to be inserted deep into the tank without exposing the tank to the outside air. It's basically just a long stainless tube that is welded to the underside of the lid and sealed (welded) on the end.

The peltier heating/cooling module is working pretty well despite the copper block soldering mishap. The thermal conductivity is not nearly as good as it should be, but it still seems to work well enough. My original plan was to use two separate peltier modules, but so far, one seems to be sufficient. Without any insulation on the tank, the device held a 15*F difference from ambient temperature, so this project may not even need much insulation.

The temperature setpoint is 67*F. For actual beer brewing, I'm thinking 64*F will be the target ale brewing temperature. So far, I am just using proportional control with a very high proportional constant. The tank has so much volume, and the heating/cooling power of the peltier is relatively tiny, so there isn't much tendency to oscillate.

Tuesday, October 13, 2009

Flattening parts with glass-backed sandpaper (what to avoid)

In the past, I've used sandpaper that has been glued or double-stick taped to a large piece of glass to flatten small parts. Apparently, this only works well when the sandpaper is stationary and the part is moved. The part will naturally be flattened by the random passes on the sandpaper.
I tried to adapt this technique where the glass was moved and the part was stationary. It didn't work. The part ended up very smooth, but not flat. It's too difficult (apparently) to hold the glass at the same exact orientation for every stroke. I ended up mounting the part back in the mill and using a wide diameter end mill to flatten and smooth the surface in one pass.

Stainless steel conical beer fermenter Pt.6

I decided to scrap the idea of using my ring burner shown in "part 5" of my conical fermenter series of posts. Instead, I started reading about home-built propane burners for use in small metal-working forges.

These sites were very helpful:

I decided to follow Mr.Zoeller's design, for which he was kind enough to post a PDF and provide great instructions.

I used an 1/8" NPT brass cap to seal the end of the 1/8" pipe nipple instead of a Tweco Mig tip. I drilled a .035" hole in the center of the brass cap after machining the sides and face smooth.

I used a 3/4" to 3/4" extender as a flare. I cut out the threads on the lathe, leaving a 1:12 taper on the interior surface. I tested the burner briefly before cutting the taper, and I'm not sure how much it really helped. I never tested it without the flare.

This is really a very good design. It can be built from parts found at any hardware store, and it only requires a couple holes to be drilled. The performance seems to be quite good. I do not have any other burners to compare it to, but I am quite pleased. It doesn't like to run at very low pressures. The flame will be drawn back into the tube, and it starts to sputter (as well as heat up the tube). Above 3 or 4 psi, it runs like a champ, and the adjustable air shutter is a critical piece. Without the air shutter, the flame is very lean and might blow itself out. I kept the shutter half-closed, and this seemed to produce a very neutral flame.

I fitted the conical with its valves and added 1 gallon of tap water. The burner is mounted by simply placing it between two short stainless pipes that I welded onto the frame rail. There is currently nothing holding the burner in place except gravity. I'll probably add a pin or strap to prevent the burner from accidentally falling.


I achieved a full rolling boil in 20 minutes (1 gallon of water). I started out fairly low with the gas pressure, and gradually increased it, as I saw nothing bad happening.

Sunday, October 11, 2009

Stainless steel conical beer fermenter Pt.5

I found a 0-10 psi adjustable propane regulator at Home Depot. It was a closeout item with a price of $4.99! I built a circular burner from 5/8" copper tubing and soldered in some "jet burners" from the ubiquitous 23-jet wok burner.

The 23-jet burner is available in natural gas and propane versions. I ordered the propane version from (it was on sale for $20.03 a few weeks ago), but they might have sent me the natural gas version. I suspec this might be the case because the burner runs very rich. Take a look:

The yellow tips on the flames show that there is a lot of excess fuel. The flames are jumping off the burners probably because the mixture is too rich to start combustion inside the burner tube.

I ordered some hypodermic tubing from McMaster and made the jets smaller by press-fitting the hypodermic tubing into the existing jets. This changed the jet size from about .023" to .012". Now, the jets seem to burn too lean, and have a very hard time staying lit. The slightest breeze blows the flame out. When the burner was running too rich, it also could be blown out by slight breezes. I think the burners are not designed very well. The original orientation in the 23-jet burner caused a lot of turbulence to be generated -- it positioned the jets to aim into each other's path. This might have been a required design element to prevent the flames from being blown out.

Anyway, I'm considering a different propane burner design. More later.

Stainless steel conical beer fermenter Pt.4

Today I built a three-legged support structure to hold the beer fermenter. My original design called for welding three square cross-section tubes to the sides of the conical tank. I decided against this method because I wanted to ability to remove the tank from the stand, and I was also a little worried about having inadequate argon coverage on the weld backside (in the tank).

The three legs are only held together by the welds near the ground. The tank just rests on top of the legs. I may add some strapping to prevent the legs from splaying outward from the conical tank, but so far, this doesn't seem to be much of a problem. The legs are all 304 stainless steel - same as the tank.

I was surprised how little filler rod I needed for these welds. Next time, I will make my tack welds much smaller, because the weld bead itself was very tight, and the globs of filler from the tack welds were annoyingly large.

I welded some stainless nuts to small sheet metal structures, then welded the assemblies to either side of the copper heat block. The two nuts will allow me to sandwhich the Peltier between a large heatsink and the copper block. I'll use nylon screws to prevent heat transfer and also to make the compression on the Peltier more gentle and balanced.

Thursday, October 1, 2009

Quickly tapping (threading) holes in plastic

For my day job, I often have to tap (cut threads into) holes in plastic that will receive screws. This can be done by hand with a standard tap wrench, but it's also possible to do with a hand drill. I bought a small 3/8" square drive adapter that has a 1/4" hex shank. This was intended for use in cordless screwdrivers which accept hex shanks, but a drill chuck will grab the hexagon just fine. I also bought a set of adjustable tap chucks that have a 3/8" square drive hole.
The smaller chuck goes from #2 taps up to about #10, and the larger for #10 up to 3/8".

For plastic, I use lots of distilled water as coolant. If I am tapping a blind hole, I usually just fill it up with water. The nice thing about using distilled water is that it leaves no residue after being blown clean with compressed air.

Tapping a hole with the hand drill works best for a certain range of sizes:

In ABS, I would use the drill for any size #2 through 1/4"

In acrylic or Delrin, I would probably only use the drill for #6 through 1/4"

The really small taps sometimes clog up, even with coolant, and the drill doesn't provide enough sensitivity to avoid snapping the tap. ABS is so soft, a clog would just be pushed away, whereas in acrylic or Delrin, it might jam.

For sizes larger than 1/4", I would probably use a tap wrench because they take a lot of torque, and it's difficult to keep the drill straight and have it deliver enough torque to spin the tap.

I like using the chrome-plated taps because the finish will not rust (a concern since I use water as a coolant), and the chrome is supposed to have a lower friction coefficient than bare high-speed steel.

For sizes smaller than 1/4", I would only use a bottoming tap in plastic. There is no reason to use a plug or taper tap because the bottoming tap makes a cleaner cut, and actually produces less friction and heat than plug or taper taps. In harder materials it makes sense to cut gradually, but plastic is so soft, it will just melt if the tap keeps making light passes that rub against the surface.

Tuesday, September 29, 2009

Google Checkout is making PayPal look good

This post is definitely off-topic for my blog, but I am extremely disappointed with Google Checkout's Merchant services, and I want to publicize the difficulty.

I have a customer that placed an order on my website and paid with Google Checkout. Her credit card was listed as "declined", so she called her credit card company to find out why. The credit card company responded that they had no record of the Google Checkout transaction at all, and there were no declined transactions on the account.

Of course, Google Checkout has no support phone number. Apparently they recently removed their support email address and online support contact form.

UPDATE: I found the "contact us" link at the bottom of the page, which allows merchants to enter an order number and request assistance, but there is no text entry box to actually describe the exact problem.

So now I am stuck with a very frustrated customer and perhaps a lost order. Worse, I have no way of fixing the situation because Google Checkout has no way of being contacted with details about the problem. Thanks, Google.

Here's some links to others who have had problems all stemming from the complete lack of merchant support.

Thursday, September 24, 2009

Telescope magnification

A friend recently asked me about telescopes, and it made me think about the pictures that I took with my telescope which I haven't looked at in years. This series of photos was a test of the range of magnifications possible with a couple camera lenses and the telescope.

These photos were shot with a Nikon FE2, with some run-of-the-mill 400ASA color film. The photos were developed and printed 4x6 at a 1-hour photo place. I scanned the photos with a flatbed scanner.

50mm Nikon lens. This is essentially the field of view that normal human vision has.

135mm Vivitar lens.

2032mm Celestron Nextar 8" SCT telescope. Prime focus. The ceramic insulator is just visible in the lower right corner.

The same telescope using eyepiece projection -- I forget the focal length of the eyepiece. The white halo in the center of the image is an artifact of my shoddily-mounted eyepiece setup.

A shorter focal length eyepiece increases the magnification even more. This is probably a 6mm eyepiece, giving 2032/6 = 338x magnification. The photo is blurry, but this is mainly due to tiny vibrations in the 'scope and camera. When viewing this directly through the eyepiece, the image is pretty sharp since human eyes and brains have better image processing than cameras.