It turns out that lots of MBP models have a well-known issue with the headphone port, and this can cause the internal speakers to become disabled. Actually, they’re disabled as a side-effect of digital output being enabled. The headphone port is used for both electrical and optical connections, and the internal switch managing this can sometimes enter the “optical connector present” state for no apparent reason.

Here’s one thread describing this issue, and Google turns out many more.

However, the reason that I’m writing this is that my machine (2010 17″ MBP) seems to suffer from a variation of this problem. All descriptions of the issue I found were rather old, and in all cases it was reported that the red light (ie. the optical signal stream) was turned on when the internal speakers were disabled. On my machine, the red light was visible only some of the time.

Doing a software update, a reboot and even an SMC reset did not help. I eventually fixed the issue by moving the headphone jack slowly in and out of the port while wiggling it a little bit. It took maybe 15 tries before it worked…

To monitor your (lack of) progress, open the System Preferences, go to the Sound pane and select the Output tab.

  • In the broken state, the topmost item will read “Digital Output” and a red light may or may not be visible from the headphone socket
  • When the headphone jack is inserted, this should change to “Headphones”
  • The non-broken state is “Internal Speakers”. This is when you have managed to clear the switch (HW or SW, I don’t know) that is stuck in the “optical connector present” state.

It seems like I’m going to be haunted by my disastrous server upgrade for some time to come.

The server has gitosis installed, which is what I use for serving my private Git repos. Now, when trying to clone a repo (from another computer), I suddenly got a stack trace:

/usr/bin/gitosis-serve:5: UserWarning: Unbuilt egg for setuptools [unknown version] (/usr/lib/python2.6/dist-packages)
  from pkg_resources import load_entry_point
Traceback (most recent call last):
  File "/usr/bin/gitosis-serve", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 2655, in <module>
    working_set.require(__requires__)
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 648, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 546, in resolve
    raise DistributionNotFound(req)
pkg_resources.DistributionNotFound: gitosis==0.2
fatal: The remote end hung up unexpectedly

It turns out that this was because Python had been upgraded to 2.6. Fixing it was extremely easy: Re-install gitosis with the current version of Python:

git clone git://eagain.net/gitosis

cd gitosis

sudo python setup.py install

Now I just need to figure out how to fix the charset encoding in my MoinMoin wiki…

Thinking like a sysadmin

August 24, 2010

I’ll admit right away: Sitting under our staircase, hunched over my laptop, is not really my idea of a great weekend.

I spent a significant part of last weekend in deep frustration. My home server had crashed, and it was absolutely my own fault. When this server is down, it means no internet connection in the house. Plus, a mailing list, my wiki, redirection to my blog and a few other services are down. So obviously this needed to be fixed, and fast.

The trouble began when I tried to create a RAID array last week. After some hassle with a cheap SATA controller “with Raid”, I decided that I would just go for a software RAID. Now, in an attempt to be responsible and actually prepare this operation, I googled a bit and found various posts about how to go about doing this in Ubuntu, caveats to avoid and so on. Among other interesting facts, I discovered that the kernel I was running was known to cause some trouble with RAIDs.

So time to ugrade to the newest release, a leap of 3 or 4 Ubuntu releases. Unfortunately, my patience was running low at this point, so I ignored the HUGE warning and started the upgrade over my SSH connection. Because I couldn’t be bothered to pull out the server from under the staircase and attach keyboard and monitor to it.

As you will have guessed by now, this was an enormous mistake. One of the stupidest things I have yet done in my career as an amateur sysadmin. Because of course, somewhere in the course of the upgrade, something went wrong and broke the network connection. Along with DNS, DHCP, internet connectivity and everything else we rely on this machine for.

After a reboot, I was still unable to contact the machine. So I had to pull it out and attach an actual monitor to it. To my horror, it turned out that the boot process died instantly, because it was unable to mount the root filesystem. WTF?

Let me just cut to the chase here, because too many hours were spent trying out solutions that just didn’t work.

The solution was slightly interesting, though. Not having an internet connection (except on my HTC Hero) made it pretty hard to google for possible solutions, look up GRUB docs etc., so I ended up taking a different approach. I had an Ubuntu 10.4 installer CD lying around, so I did a fresh install using some free space on the hard drive. Then, I compared the GRUB configurations of the broken and the fresh installations. It turned out that the upgrade had been interrupted before it had created an initrd for the new kernel! So I was a bit surprised that it had updated the GRUB config to a half-baked state – the entry in menu.lst contained a kernel line but no initrd.

So stealing a fresh kernel+initrd from the new installation and Voila!, my system was back to normal (except for lots of unconfigured packages etc.).

Lesson learned: As a software developer, I’m enthusiastic, optimistic and sometimes downright reckless. As a sysadmin, pretty much the same. A good sysadmin needs to be conservative and cautious, and I understand why they sometimes get annoyed with us developers.

Keep this in mind the next time your local sysadmin doesn’t “just update that shit” right away.

 

I have decided to build the one thing I know the world doesn’t need: Another Twitter client!!

There must be hundreds out there already, and dozens of them very good. However, after trying out quite a few of them, I’m not really pleased. A quick roundup of the ones I know of:

  • Twitterific is the best so far, but it displays ads every hour (unless you pay), and I can’t really get used to the overlay-style interface. Plus, it often reports communication errors for no reason.
  • TwitterPod is actually OK, but very wierd…! It features a completely useless “QC” mode, where tweets flicker by, intertwined with user mugshots and psychedelic colorized patterns (but of course, you don’t have to use that mode). Actually, I can’t really remember why I stopped using TwitterPod. Probably just because it is wierd and Japanese and alien. It didn’t really have a cool feel to it.
  • The web-based interface (nah)
  • All the AIR-based clients: No, I don’t want AIR on my Mac right now. Maybe some day when I run out of more interesting stuff to play with.
  • All the Android/iPhone/Windows Mobile based ones: No, I want it here on my laptop

So there you have it, nothing is good enough right now. But what would be good?

Here are my thoughts so far about the client I want to build:

  • Open source. I can’t be bothered to do it all myself.
  • Runs on my Mac. If someone wants to port it, great.
  • I want an easy way to track “conversations” between me and some other dude (there probably a funky term in Twitterish for this).
  • When I add a tweet, I expect it to appear in my timeline, or what it’s called, immediately. It should not wait for the next batch of updates.
  • Builtin support for quickly searching for people to follow, using first-, last- or username.
  • Easy way to create all sorts of filters. Most simple method would be to show only the tweets of one followee.
  • It should be easy to mute and unmute friends. The name of a muted friends appears in red when others address him.
  • Every tweet should be colorcoded. Each friend should get a “lease” on a particular color. The lease should expire after some period of inactivity.
  • Fancy visualization: A large canvas (optinally full-screen) on which tweets are clustered by relationship. Ie. when they respond to each other, they form a little group of tweets with arrows showing response directionality. Each tweet should fade in color as it ages.

I will probably be writing the client in Ruby using RubyCocoa.

I am not fooling myself here. I know that someone else has probably covered the features mentioned above in a client much cooler than I could ever come up with. There must be hundreds of alternatives listed on this page alone.

However, there does seem to be a lack of decent open-source Twitter clients. At least ones that are not based on AIR.

Oh well, let’s just see when I get around to actually coding this. I have all sorts of half-baked ideas these days, but way too little spare time to realize any of them.

Drop me a comment if how have an idea for a killer feature to include.

Pre-publish update: OK, so I found one more client that almost discouraged me from writing my own: Lounge.

It looks very nice and IMO is easier to use than Twitterific because it uses a regular window instead of an overlayed one (or whatever it’s called). However, Lounge is an early beta so some features are incomplete or simply missing. For example Growl integration is pretty basic and the Vanity category doesn’t seem to work(?).

One feature that could have been great is the ability to display pictures from Twitpic inline. However, only thumbnails are shown, so you need to launch your webbrowser anyway. Pretty useless then…

Also, it’s closed source – in fact the beta expires on July 1, which makes me a bit suspicious…what then, will I have to buy it?

So in conclusion, it looks quite promising, but I still need to write my own client ;-)

My first AVR-based project

August 16, 2008

I have always been fascinated by electronics. As a child, I tore apart several rather expensive appliances to see how they worked. Much to my parents’ grief, of course.

However, since I got into software development, I haven’t given it much thought. Moving several levels of abstraction away from the hardware, your focus shifts quickly to completely different areas.

But recently, this project caught my attention for some reason. So even though I ended up implementing it completely differently, I couldn’t stop thinking about the potential of being able to write code for tiny, cheap embedded processors.

I’m not sure why I have never thought of this before. I have considered writing software for PDAs, but they’re pretty expensive, and the platform choices are poor. Windows Mobile is a joke, and Palm OS is not very appealing either.

So I decided to take a big step closer to the iron. Knowing nothing about the state of this field, I simply googled for a few starting points. I ended up buying the very cool USBtinyISP programmer kit (and absolutely enjoyed the process of assembling it).

Also, I got the ATtiny26 development board from Active Robots.

This last item, I have later discovered, is probably somewhat outdated. What you want for electronics prototyping these days is the Arduino.

Anyway, the great thing about the ATtiny is that it’s cheap (the processor itself is about $4) and it doesn’t consume a lot of power.

OK, so what did I do for my debut project? Nothing very interesting, I’m afraid. I wrota a program that simply morses a sentence using the LED built into the development board. I used the GNU toolchain (avr-libc et al) for writing the program and avrdude for flashing it onto the processor. Works great on both Linux and OSX.

In action, this is what it looks like:

And yes, I realize that the quality of the video is too crappy to distinguish the pulses.

Here is the complete source code for this project:

#include
#include
#include
#include
#include

/*
 * The morse alphabet.
 *
 * 0: Short pulse
 * 1: Long pulse
 */
const char ltr_a[] PROGMEM = "01";
const char ltr_b[] PROGMEM = "1000";
const char ltr_c[] PROGMEM = "1010";
const char ltr_d[] PROGMEM = "100";
const char ltr_e[] PROGMEM = "0";
const char ltr_f[] PROGMEM = "0010";
const char ltr_g[] PROGMEM = "110";
const char ltr_h[] PROGMEM = "0000";
const char ltr_i[] PROGMEM = "00";
const char ltr_j[] PROGMEM = "0111";
const char ltr_k[] PROGMEM = "101";
const char ltr_l[] PROGMEM = "0100";
const char ltr_m[] PROGMEM = "11";
const char ltr_n[] PROGMEM = "10";
const char ltr_o[] PROGMEM = "111";
const char ltr_p[] PROGMEM = "0110";
const char ltr_q[] PROGMEM = "1101";
const char ltr_r[] PROGMEM = "010";
const char ltr_s[] PROGMEM = "000";
const char ltr_t[] PROGMEM = "1";
const char ltr_u[] PROGMEM = "001";
const char ltr_v[] PROGMEM = "0001";
const char ltr_w[] PROGMEM = "011";
const char ltr_x[] PROGMEM = "1001";
const char ltr_y[] PROGMEM = "1011";
const char ltr_z[] PROGMEM = "1100";

PGM_P alphabet[26] PROGMEM = {
    ltr_a,ltr_b,ltr_c,ltr_d,ltr_e,ltr_f,ltr_g,ltr_h,ltr_i,ltr_j,ltr_k,
    ltr_l,ltr_m,ltr_n,ltr_o,ltr_p,ltr_q,ltr_r,ltr_s,ltr_t,ltr_u,ltr_v,
    ltr_w,ltr_x,ltr_y,ltr_z
};

void sleep_msecs(int msecs)
{
   /*
    * The argument to _delay_ms must be constant (ie. known at compile-time).
    */
   int i;
   for(i = 0; i &lt; msecs; i++){
      _delay_ms(1);
   }
}

void set_led_state(int state)
{
   PORTB = (state == 1) ? _BV(6) : _BV(0);
}

/*
 * Emit single pulse
 *
 * Length choices are:
 * 0: short
 * 1: long
 */
void emit_pulse(int length)
{
   set_led_state(1);
   sleep_msecs((length == 1) ? 210 : 60);
   set_led_state(0);
   sleep_msecs(100);
}

/*
 * Emit a sequence of pulses, eg. "1000" for the letter "b".
 */
void emit_pulses(char *pulse_str)
{
   int pulse_str_len = strlen(pulse_str);
   int i2;
   for (i2 = 0; i2 &lt; pulse_str_len; i2++) {
      emit_pulse(pulse_str[i2] == '1');
   }
}

void emit_letter(char l)
{
   if (l == ' ') {
      sleep_msecs(700);
      return;
   }

   char *buf = malloc(8 * sizeof(char));

   int index = l - 'a';
   PGM_P p;
   memcpy_P(&amp;p, &amp;alphabet[index], sizeof(PGM_P));
   strcpy_P(buf, p);
   emit_pulses(buf);
   free(buf);
}

void morse_msg(const char *msg)
{
   int len = strlen(msg);
   int i;
   for (i = 0; i &lt; len; ++i) {
      emit_letter(msg[i]);
      sleep_msecs(350);
   }
}

void do_morse(const char *msg)
{
   for(;;){
      morse_msg(msg);
      sleep_msecs(2500);
   }
}

int main(void)
{
   /* Init IO */
   DDRB = _BV(6); /* make the LED pin an output */

   do_morse("er der mon mere kaffe");

   /* Not reached */
   return 0;
}

In case you’re wondering, the morsed message, “er der mon mere kaffe”, is danish for “I wonder if there’s any more coffee”. Indeed, the first thing that sprang to mind when I finally got the software working.

If you’re a cat owner, you know that cats love to drink from the faucet!
Being a cat owner myself, I was pretty excited to learn about this Cat Faucet project by Sixerdoodle Electronics. I have often thought about building something similar myself, but I had never gotten around to it.

However, even though the design of the Sixerdoodle Cat Faucet is very elegant, I find it more complicated than necessary (mainly because they wanted to keep it low voltage, it turns out).

So I started wondering how to build the simplest possible cat faucet. This is what I came up with:


(Open above image, with notes, in a new window)

(Diva enjoying the running water)

The complete list of components:

  • a solenoid from an old dishwasher
  • a movement sensor (the kind usually used to light up a driveway)
  • a few bits of plumbing
  • a piece of gaffer tape to limit the area monitored by the sensor

(Solenoid from an old dishwasher)

(The movement sensor, pointed straight down)

That’s it. The flow of water is controlled simply by adjusting the position of the red valve that lets water into the system. The sensitivity and timeout of the sensor can be controlled with small knobs on the underside.

My wife put a little bowl underneath the faucet to allow the cats to drink from a surface of water as well as from the running water. Excess water simply spills down the drain below.

Contrary to the Sixerdoodle design, my cat faucet is not low voltage (it runs on 230V, our mains voltage in Denmark). However, because both components were designed to be safe and withstand pretty rough conditions, this does not worry me at all.

(The finished setup, tucked away under a small shelving unit)

(Obviously, it takes a little practice!)

Follow

Get every new post delivered to your Inbox.