Wednesday, December 16, 2009

Software tips: Ninite - excellent tool for installing multiple freeware apps

My harddrive started to make lot's of wierd noises the a while back so I took the preemptive decision to buy a new one. And luck has it I was following Macegrs twitter-feed, where he tweeted about how terrific Ninite was when he had to reinstall Windows 7. I gave it a shot yesterday and I can do nothing more than to agree with him. I got all my apps installed quickly and effortless - just as advertised.

Tuesday, December 8, 2009

Wireless issues on Macs

Problem: My coworker had some issues with her wireless network at home. Her Macbook running OS X 10.5 Leopard would connect to their home network without any problems. But her husbands Powerbook and their older stationary Mac would not connect at all. There were no hardware problems with the Powerbook, in fact it worked without a hitch at her husbands job. And ofcourse they had tried retyping the password a million times.

Solution: While helping another friend of mine with his AirPort Express I came across a couple of posts in different forums that suggested using WPA2 Personal encryption (AES) instead of WPA1 Personal encryption (TKIP). We tried that and it temporarily solved the issues he had, but there were other problems in that network. However, when I told my coworker to change her encryption from WPA1 (TKIP) to WPA2 (AES) it worked like a charm and all the computers in the network got connected right away.

Short version: If you have wireless issues (inability to connect, dropping connection) on Macintosh hardware give WPA2 (AES) a try it might work.

Thursday, December 3, 2009

DIY ambient tv light inspired by ME!!

Szymon took my Arduino powered mood light to another level. Check out his DIY ambient TV light. Me myself and I are very proud to have inspired such a project and really happy to see stuff I've created evolve in other peoples hands.

Wednesday, December 2, 2009

Trying to recover data from a failing hard drive

My brother in-law asked me to take a look at his girlfriends computer (a laptop) that wouldn't boot up. Quite soon it stood apparent that the computer failed to find a bootable hard drive. I had a similar issue after trying to install Fedora 11 on my laptop.
This issue, I found out, had something to do with the SATA controller being set to AHCI- or Legacy-mode. I got my drive bootable again by fiddling with this setting a couple of times and rebooting the computer. When I got the drive to boot again, I set it to AHCI-mode which is the default.
But that was my fully operational drive, not the one in question here.

Trying it on another computer

This drive wouldn't even show up in BIOS. Since it is a laptop there's really not much I can do but remove the drive and hook it up to another computer. So I bought a SATA/IDE adapter kit from Deltaco, a small device that let's me connect any 2.5" and 3.5" PATA or SATA drive to a USB-port.
I hooked the drive up and connected it to my own laptop. I could hear the drive spin up and make some other noises before it showed up in both Windows Vista (not as a regular drive, but visible in the administrative tools disk management) and Ubuntu Linux. Since it's far easier to find freeware resuce applications under Linux I went with Ubuntu.

Tools of rescue

From what I found from googling hard drive resuce under linux there seemed to be two main applications to use. GNU ddrescue and TestDisk both available in the default Ubuntu repositories under the names gddrescue and testdisk.
First it gave TestDisk a try, but since it didn't even list the drive I resorted back to a tutorial on the TestDisk site on how to recover data from a damaged hard disk using GNU ddrescue. But unfortunately this seemed to have quite little effect. All I got was that the rescue was done but no data what so ever was copied. I tried fdisk, cfdisk and gparted to access the drive directly but all of them reported failure. As I'm writing this I'm starting to wonder wether or not the "visible" drive is in fact the USB-controller and not the drive itself? (edit: It is!)

The last resort: Stick it in the freezer
So now I was stuck with the quite annoying feeling that the drive was broken beyond my ability to resuce it. And I wanted so to be the hero here and let the others bask in my geeky glory. However after a good nights sleep I started to recall another more unorthodox way of getting data from a failed drive by sticking it in the freezer.
Again I went to the great oracle of google and found many different success testimonials using this procedure. The important part seemed to be to protect the drive from moisture by bagging it in a zip lock bag before sticking it in the freezer. There were also some methods involving sticking the drive in the oven to dry it out then freezing it again, but that seemed a bit to tedious.
To protect the drive from static I first put it in a anti static bag then in a plastic freezer bag (I guess that's the swedish equivalent to a zip lock bag, minus the zip lock) then I sucked all the air out of the bags, just like my mother tought me to do when freezing freshly baked bread. Then I took another freezer bag and put the bagged drive in and sucked the air out of that one too. Then it was freezer time for the drive. My freezer is set to - 18 °C and the drive will be in there for about ten hours before I do the first test.

Well the freezing didn't help. My guess is that it is a mechanical problem and the only hope now is to pay the big bucks to get a specialized disk recovery firm to take a look at it.

Tuesday, October 20, 2009


I got kind of bored of my digital picture frame, like i normally do when a project is finished. So I wanted to do something else with it. One of the things I wanted to try to use was the command line interface instead of X. The idea was to get some nice scrolling text on the screen. An IRC-frame sounded like a nice idea until I realized I really want the system to be automatic and since IRC sometimes requires you to interact I decided to go with twitter instead.

I surfed around and found that PTT (Python Twitter Tools) seemed to be what I needed. To install PTT in Debian (I guess the same goes for all other debian derivatives like Ubuntu and so on) you first need to install the packages python-twitter and python-setuptools, and their respective dependencies.
To do this simply type the following in a console/terminal:
sudo aptitude install python-twitter python-setuptools

Then install installed PTT with:
sudo easy_install twitter

Now it's just a matter of either using the proper command line options to get PTT to do your bidding. To get an idea of what you can do simply type:
twitter -h

Since I like config-files I created one in my home dir called .twitter (this also happens to be the default config file PTT looks for. This is what my .twitter file contains:

password: mytwitterpassword
format: verbose
format: ansi

The email and password options are pretty self explanatory if you have a twitter account. Format however is the way twitter presents itself on your screen.
format: verbose | Prints out the full twitter post rather than just one line as per default.
format: ansi | Uses ansi coloring on the different usernames.

Since .twitter contains your password it can be a good idea to only allow your user to read it:
chmod 400 .twitter

Now that I had PTT working the way I wanted I simply added "twitter -r" to my .bash_profile to have it automatically launch after my system boots up. The "-r" causes PTT to continue running and updating the twitter feeds every five minutes.

Tuesday, September 22, 2009

Determine if user is logged in remotely or locally

Since I do all the maintenance on the digital picture frame via ssh I don't want the same login scripts to run when i log in remotely as when I log in locally. Well to be more specific I don't really log in locally but the user I have created logs in automatically when the DPF is turned on and from there on a number of things start. Needless to say I don't need to run "startx" everytime I log in via ssh.

So I wrote a small script to help me determine whether or not I was logged in locally or remotely (via ssh). The script is in its bare form here, I use it in my .bash_profile but you might find another use for it.

Important note: This script doesn't really determine if a user is logged in locally or remotely but rather using a tty or pts although the latter usually means that the user is logged in remotely, but not always. ;)

# tty vs pts checker by Markus Ulfberg 2009-09-22
# Inteded use is running different scripts wether
# the user logs in remotely or locally.

# Get the name of the tty the user is on.
# strip everything but tty or pts from the string that "tty" produces.

# Check if it is tty or pts.
if [ $USER_TTY == 'tty' ]
echo "You are logged in locally using: $FULL_USER_TTY"

if [ $USER_TTY == 'pts' ]
echo "You are logged in remotely using: $FULL_USER_TTY"
# Return failure if it is neither.
echo "Failed to establish type of tty"

Formatted for blogger using:

Wednesday, June 17, 2009

Waking up a sleeping printer

The printer (a Canon CLC 3220) at my office takes quite some time to warm up and calibrate after waking up from sleep mode. Anyone who wants to print out something at the beginning of the work day knows this. And it can be quite stressful if you have to get something out for an early morning meeting.

Currently sleep mode is activated after four hours of inactivity. A quite reasonable time I think. So instead of fiddling with the sleep setting I added the following line to the crontab of our server:

   0    7    *    1-6,8-12     1-5    echo | lpr

This line prints an empty page every morning at 7 each workday, except in july when the office is closed. Thus the printer is calibrated and ready to go when people start arriving at the office around 8 in the morning.

Our server is an Xserve running OSX and for this to work I had to install the printer drivers on the server. Also setting the printer to default helps I think (though I didn't have to since we only use one).

Tuesday, May 19, 2009

Arduino Mood light controller

UPDATE: New source code and videos here.

I love black and white, especially white. But I also love color, however I tend to change what type of color I like ALOT. So when saw the concept of coloring a surface with light I knew I had to try it at home.

The hardware I decided to use my new found love the Arduino micro controller to control some sort of light. At first I thought about using IKEAS DIODER but as MikMo pointed out the RGB LED strip from Deal Extreme is quite a much better deal. A little over $16 and free shipping from Hong Kong.

What I wanted to achive

  1. Select a specific color
  2. Pulsate the specified color
  3. Random color swash i.e. go smoothly from color to color.

Controlling the colors
I decided to use a ULN2003 with the Arduino to control the DX RGB LED strip. It can handle enough amps to drive the LED strip and it's also alot neater than multiple transistors.

Arduino control of LED strip via ULN2003
RGB LED strip 400 mA @ 12 V

R1 = 10K Potentiometer (Color selector) R2 = 100 Ohm (Pin protector)
R3 = 10K Ohm (Pulldown resistor) S1 = Switch (Mode selector)

One potentiometer to rule them all
When I first started out mixing RGB colors I used three potentiometers, one for each color. This ofcourse gives you a high resolution but also three different knobs. So inspired by the Philips LivingColors, I decided to streamline my color control using only one potentiometer connected to an analog in pin on the Arduino.

As you can see in the picture below the value 0 on the analog pin is full red and then changes through the color circle back to red as the value reaches 1023.

Note: I used Adobe Illustrator to create the image above, to help me think, but when using gradient fill in Illustrator some colors take up more space than others. At least it looks like that if you space them evenly. I don't know if this also is the case with my color mixer, but I haven't really bothered to figure that out.

At first I used alot of steps before I realized I could remove some of them. Orange for example is produced when you have more red than green on your way to yellow (full red and full green). But purple requires both full red and full blue. Hence some I could remove some steps and had to keep some of them.


Button presses in the video
Filmed in broad daylight, hence the colors don't really come out too well.
1. On - Select a color with the color selector.
2. Pulse - Pulsate the selected color.
3. Random/Cycle - Cycle randomly through the palette.
4. Off.

Pulse Mode
Filmed in a dark room with the RGB-strip hidden behind the laptop screen.

Random/Cycle Mode
Filmed in a dark room with the RGB-strip hidden behind the laptop screen.

Source code

UPDATE: New source code and videos here.

The finished code with four modes, also available as a download here.
Formatted for Blogger with:
RGB LED controller
4 modes: off, color select, color pulse and random cycle/pulse
By Markus Ulfberg 2009-05-19

Thanks to: Ladyada, Tom Igoe and
everyone at the Arduino forum for excellent
tutorials and everyday help.


// set the ledPins
int ledRed = 10;
int ledGreen = 9;
int ledBlue = 11;

// color selector pin
int potPin = 1;

// lightMode selector
int switchPin = 2;

// light mode variable
// initial value 0 = off
int lightMode = 0;

// LED Power variables
byte redPwr = 0;
byte greenPwr = 0;
byte bluePwr = 0;

// Variables for lightMode 2
// variables for keeping pulse color
byte redPulse;
byte greenPulse;
byte bluePulse;

// Set pulse to down initially
byte pulse = 0;

// floating variables needed to be able to pulse a fixed color
float redFloat;
float greenFloat;
float blueFloat;

// the amount R,G & B should step up/down to display an fixed color
float redKoff;
float greenKoff;
float blueKoff;

// Variables for lightMode 3
// set the initial random colors
byte redNew = random(255);
byte greenNew = random(255);
byte blueNew = random(255);

// misc interface variables
// potVal keeps the value of the potentiometer
int potVal;
// value from the button (debounce)
int switchVal;
int switchVal2;
// buttonState registers if the button has changed
int buttonState;

void setup()
pinMode(ledRed, OUTPUT);
pinMode(ledGreen, OUTPUT);
pinMode(ledBlue, OUTPUT);

pinMode(potPin, INPUT);

pinMode(switchPin, INPUT);
buttonState = digitalRead(switchPin);

// serial for debugging purposes only

void loop()
switchVal = digitalRead(switchPin);      // read input value and store it in val
delay(10);                         // 10 milliseconds is a good amount of time
switchVal2 = digitalRead(switchPin);     // read the input again to check for bounces
if (switchVal == switchVal2) {                 // make sure we got 2 consistant readings!
if (switchVal != buttonState) {          // the button state has changed!
if (switchVal == LOW) {                // check if the button is pressed
if (lightMode == 0) {          // light is off
lightMode = 1;             // light is on and responds to pot
} else {
if (lightMode == 1) {
lightMode = 2;           // light pulsates in the latest color from pot
} else {
if (lightMode == 2) {
lightMode = 3;           // light changes randomly
} else {
lightMode = 0;             // light is off 
buttonState = switchVal;                 // save the new state in our variable
if (lightMode == 0) {      // turn light off
analogWrite(ledRed, 0);
analogWrite(ledGreen, 0);
analogWrite(ledBlue, 0);
if (lightMode == 1) {        // set fixed color

// read the potentiometer position
potVal = analogRead(potPin);

if (potVal > 0 && potVal < 170) {
redPwr = 255;
bluePwr = 0;
analogWrite(ledRed, redPwr);
greenPwr = map(potVal, 0, 170, 0, 255);
analogWrite(ledGreen, greenPwr);
analogWrite(ledBlue, bluePwr);

if (potVal > 170 && potVal < 341) {
greenPwr = 255;
bluePwr = 0;
analogWrite(ledGreen, greenPwr);
redPwr = map(potVal, 341, 170, 0, 255);
analogWrite(ledRed, redPwr);
analogWrite(ledBlue, bluePwr);

if (potVal > 341 && potVal < 511) {
greenPwr = 255;
redPwr = 0;
analogWrite(ledGreen, greenPwr);
bluePwr = map(potVal, 341, 511, 0, 255);
analogWrite(ledBlue, bluePwr);
analogWrite(ledRed, redPwr);

if (potVal > 511 && potVal < 682) {
bluePwr = 255;
redPwr = 0;
analogWrite(ledBlue, bluePwr);
greenPwr = map(potVal, 682, 511, 0, 255);
analogWrite(ledGreen, greenPwr);
analogWrite(ledRed, redPwr);

if (potVal > 682 && potVal < 852) {
bluePwr = 255;
greenPwr = 0;
analogWrite(ledBlue, bluePwr);
redPwr = map(potVal, 682, 852, 0, 255);
analogWrite(ledRed, redPwr);
analogWrite(ledGreen, greenPwr);

if (potVal > 852 && potVal < 1023) {
redPwr = 255;
greenPwr = 0;
analogWrite(ledRed, redPwr);
bluePwr = map(potVal, 1023, 852, 0, 255);
analogWrite(ledBlue, bluePwr);
analogWrite(ledGreen, greenPwr);
redFloat = float(redPwr);
greenFloat = float(greenPwr);
blueFloat = float(bluePwr);

redKoff = redFloat / 255;
greenKoff = greenFloat / 255;
blueKoff = blueFloat / 255;

redPulse = redPwr;
greenPulse = greenPwr;
bluePulse = bluePwr;

// Debug
Serial.print("redFLoat: ");
Serial.print(redFloat, DEC);
Serial.print(" redPwr: ");
Serial.print(redPwr, DEC);
Serial.print(" greenFloat: ");
Serial.print(greenFloat, DEC);
Serial.print(" greenPwr: ");
Serial.print(greenPwr, DEC);
Serial.print(" blueFloat: ");
Serial.print(blueFloat, DEC);
Serial.print(" bluePwr: ");
Serial.println(bluePwr, DEC);
// End debug


if (lightMode == 2) {     // pulse fixed color

// display the colors
analogWrite(ledRed, redFloat);
analogWrite(ledGreen, greenFloat);
analogWrite(ledBlue, blueFloat);

// add delay here for speed control

// pulse down
if (pulse == 0) {
if (redFloat > 10) {
redFloat = redFloat - redKoff;
if (greenFloat > 10) {
greenFloat = greenFloat - greenKoff;
if (blueFloat > 10) {
blueFloat = blueFloat - blueKoff;

// If all xFloat match 10 get pulse up
if (byte(redFloat) <= 10) {
if (byte(greenFloat) <= 10) {
if (byte(blueFloat) <= 10) {
pulse = 1;
// Pulse up
if (pulse == 1) {
if (redFloat < redPulse) {
redFloat = redFloat + redKoff;
if (greenFloat < greenPulse) {
greenFloat = greenFloat + greenKoff;
if (blueFloat < bluePulse) {
blueFloat = blueFloat + blueKoff;
// If all Pwr match Pulse get pulse down

if (byte(redFloat) == redPulse) {
if (byte(greenFloat) == greenPulse) {
if (byte(blueFloat) == bluePulse) {
pulse = 0;
// Debug
Serial.print("redFloat: ");
Serial.print(redFloat, DEC);
Serial.print(" redPulse: ");
Serial.print(redPulse, DEC);
Serial.print(" greenFloat: ");
Serial.print(greenFloat, DEC);
Serial.print(" greenPulse: ");
Serial.print(greenPulse, DEC);
Serial.print(" blueFloat: ");
Serial.print(blueFloat, DEC);
Serial.print(" bluePulse: ");
Serial.print(bluePulse, DEC);
Serial.print(" pulse: ");
Serial.println(pulse, DEC);
// End debug

if (lightMode == 3) {  // randomsize colorNew and step colorPwr to it
if (redPwr > redNew) {
if (redPwr < redNew) {
if (greenPwr > greenNew) {
if (greenPwr < greenNew) {
if (bluePwr > blueNew) {
if (bluePwr < blueNew) {

// If all Pwr match New get new colors

if (redPwr == redNew) {
if (greenPwr == greenNew) {
if (bluePwr == blueNew) {
redNew = random(254);
greenNew = random(254);
blueNew = random(254);

// display the colors
analogWrite(ledRed, redPwr);
analogWrite(ledGreen, greenPwr);
analogWrite(ledBlue, bluePwr);

Monday, May 18, 2009

Backing up a system on Compact Flash

If you have a system on Compact Flash, for instance a digital picture frame. There's a really neat way to work on the system without having to write to the disk more than once, and still do alot of updates or other changes.

What you do is that you make a disk image of the Compact Flash media and then run that image in a machine emulator like Qemu for Linux and Windows or Q - [kju:] for OSX. Once the image is booted you can, work on the system and do all sorts of changes and when you're done all you have to do is write that image back to the media it came from. Ofcourse, if you're only doing minor changes this might be unecessary but for bigger system updates or just testing out new software before going live it's really nice.

How it's done
  1. Hook up your CF-card to your host system make sure the disk is not mounted, unmount it if necessary. But before doing that find out the path to the disk i.e: /dev/sdb, /dev/hdb or something like that.

  2. Then run dd to copy the whole disk to an image.
    The dd command can cause irreversible damage to your system. If you're not sure what you're doing, don't do it.

    Syntax: dd if=path_to_disk_to_backup of=outfile
    if stands for "Input file" and of for "Output file"

    For my system I use the following command:

    dd if=/dev/sdb of=lappy586.bin conv=noerror,sync
    The added option
    conv=noerror,sync makes sure that the copy will go on even if there are errors.
    The copy might take a while depending on the size of the image you try to copy.

  3. After the copy is done you can run the image with qemu like this:
    qemu -hda path_to_diskimage

    Qemu has alot of options, if things don't work out for you the first time have a look at the manpages and other documentation. I got lucky and had everything working without any need for extra configuration when running Qemu from Debian but not so lucky when trying to run the same image from Windows Vista.

  4. Finally, to write the backup back to disk just reverse the paths in the dd command:
    dd if=lappy586.bin of=/dev/sdb conv=noerror,sync

Friday, May 15, 2009

Useful parts to keep in stock

I thought I'd put together a little list of parts one might need when starting to fiddle with the Arduino and electronics in general. Why, well I would have liked one when I started out. It would have saved me alot on unnecessary shipping.
The list is partly my own, borrowing some from Tom Igoes Making Things Talk (a book I highly recommend) and a thread over at the Arduino forum I started.

Bread boards:
I thought I would only need one or two. By experience I know better and if you're like me, working on multiple projects, it's nice to have a few. It saves you the trouble of deconstructing and reconstructing half baked projects.

Jumper wire: For the breadboard. There are alot of different models. I've used solid core wires that were labeled for use with bread boards. I don't really care for them, however I don't have any other recommendations.

DC adaptor:
The Arduino uses a 2.1 mm center positive plug. However since you never know what you might need it's quite good to get one with interchangeable plugs in different sizes. Preferably with variable voltage aswell.

  1. DC 2.1 mm jack
    Useful when using a separate power source to your projects.
  2. DC 2.1 mm plug
    Useful when powering from battery.
  3. 9V battery connector
    Same reason as above but for the other end.
  4. Headers female and male.
    Alot of different uses. Especially when it comes to connecting wires to a breadboard.


  1. 100 Ohm
  2. 220 Ohm
  3. 470 Ohm
  4. 1 k Ohm
  5. 4.7 k Ohm
  6. 10 k Ohm
  7. 22 k Ohm
  8. 100 k Ohm
  9. 1 M Ohm

  1. CdS resistor: 2-5 k Ohm
    Works as a light sensor if you hook it up to your micro controller of choice.
  2. NTC resistor: 4700 Ohm
    A.K.A. thermistor, like the above but senses heat instead.

  3. Potentiometer: 10 k Ohm
    Extremely useful when working with micro controllers.


  1. 0.1 uF ceramic (sometimes labled as 100 nF)
  2. 1 uF electrolyte
  3. 47 uF electrolyte
  4. 10 uF electrolyte
  5. 100 uF electrolyte

  1. H-bridge: L293D
    Useful for controlling DC motors and stepper motors. Allows you to switch polarity of the outputs.
  2. Darlington array: ULN2003
    Useful for controlling bigger loads such as stepper motors and LED-strips.


These are pretty much generic transistors that my supplier had in stock. If you can't find a specific transistor, just swap it out for one with similar specs.
  1. 2N2222A TO-92 NPN 40V 800mA 300MHz
  2. BC547B TO-92 NPN 45V 0.1A
  3. BC557B TO-92 PNP 50V 0.1A
  4. TIP120 TO-220 NPN Darlington 60V 5A
  5. IRF540 TO-220 N-ch MOSFET 100V 28A
  6. 2N3906 TO-92 PNP 40V 200mA

  1. Red 5 mm dim
    The most basic of LEDs.
  2. Red 5 mm clear super bright
    Together with the green and blue below it's what you need to do color mixing.
  3. Green 5 mm clear super bright
  4. Blue 5 mm clear super bright

  1. 1N4004 DO-41 400V 1A
  2. Zener BZX55C3V3 DO-35 3.3V

Voltage regulator:
  1. LM317T TO-220
    Variable voltage regulator, with two resistors you can get output voltages from 1.2 V to 37 V.

Wednesday, May 13, 2009

Automated notification of updated of external IP

Updated 2013-03-16

Script stopped working due to changes in html2text this was resolved by adding curl as a dependency.

For my DSL line I get a dynamic IP address. On the inside it's quite easy to find out what the external IP is, but on the outside damn near impossible to find out what the IP might have changed to.
To get around that problem I wrote a little script that checks the external IP and sends me an e-mail if there has been any changes.
Dependencies: curl, html2text and ssmtp.
Source formatted by and available for download on github here.
# /bin/sh

# IP checker and updater by Markus Ulfberg 2009-05-12 

# Variables
# Path where ip.txt resides or will be created if it doesen't exist already
# E-mail address, both from and to
# E-mail Subject
SUBJECT="New IP number"

# Check for ip.txt and create if it doesn't exist. 
if [ ! -s $DIR/ip.txt ] 
        # Create ip.txt
        echo "ip.txt doesn't exist. Creating ip.txt ..."
        echo "" > $DIR/ip.txt
        echo "ip.txt exists. Continuing ..."

    # Get current IP
    currentIP=`curl | html2text | grep Current | awk '{print$4}'`
    echo "Current IP: $IP"

    # Read old IP from file
    oldIP=`cat $DIR/ip.txt`
    echo "Old IP: $oldIP"

    # Compare current and old IP
    if [ $oldIP != $currentIP ]
            echo "IP has changed to: $currentIP"
            # Write new IP to ip.txt
            echo $currentIP > $DIR/ip.txt
            # Set e-mail content to new IP
            # Send the e-mail notification
            echo -e "FROM:$ADDRESS\nTO:$ADDRESS\nSUBJECT:$SUBJECT\nContent-type:text/plain\n$CONTENT\n" | `/usr/sbin/ssmtp $ADDRESS`
            echo "IP is still: $currentIP"
exit 0

Saturday, May 9, 2009

Converting the Toshiba 320CDS to a digital picture frame

Inspired by the many digital picture frame tutorials online I decided to make one myself.
First I jotted down some goals:
  1. Use a minimal amount of hardware and achive total silence.
    Solution: Strip away, speakers, battery, CD- and floppy drive. Instead of the hard drive use a Compact Flash card with a CF-IDE bridge.
  2. Use a minimal amount of wires.
    Solution: Use wireless networking.
  3. Design with a thin and flat formfactor.
    Solution: Mount everything between two sheets of transparent polycarbonate or acrylic glass (plexi glass).
  4. Run without keyboard or mouse.
    Solution: Remote control via ssh and/or vnc.
  5. Easy power up/down via the power button.
    Solution: Autologin in console and run X and other stuff from .bash_profile
    Problem: Since the Toshiba 320CDS uses an APM BIOS it cannot read events on the power button. In other words it cannot power down nicely using the power button. Any ACPI BIOS would be able to.
  6. Display a slide show of images.
    Solution: Use Feh, a very capable lightweight image viewer.
  7. Lenghten the life of the CF card by minimising disk writes/reads after boot.
    Solution: Do not use swap on the CF card, store images online, configure the system to report less.
  8. Display a Pong Clock.
    Solution: Use the pong xscreensaver.
    Problem: Won't run smoothly @233 MHz

Install a minimal debian installation
  1. Follow this excellent tutorial:

Additional Debian packages to use
  • Remote control with: ssh and x11vnc
  • Disable screen blanking in x: x11-xserver-utils
  • Wireless support: wpasupplicant wireless-tools
  • Image viewer: feh
  • Remove the mouse cursor: unclutter
  • Mount any ftp/sftp/... as local directory: curlftpfs

Set up wireless networking with 3Com Office Connect 11g PCMCIA

  1. Download the correct firmware from:
  2. Install the packages wireless-tools and wpasupplicant
  3. Follow this excellent tutorial:
  4. To use multiple networks, use the following configuration to activate roaming mode:
    • Edit /etc/network/interfaces:
      allow-hotplug wlan0
      auto wlan0
      iface wlan0 inet manual # this has to be set to manual, dhcp configuration is done later
      wpa-driver wext
      wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
      #id_str="[NAME_OF_NETWORK]" is the identifier that corresponds to the network configuration in wpa_supplicant.conf
      [NAME_OF_NETWORK] inet dhcp

    • Create a /etc/wpa_supplicant/wpa_supplicant.conf containing:
      ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev

Autologin in debian without starting x first

Follow one of the two examples here:

Starting X after autologin:
  1. Add startx to .bash_profile

Set up and use curlftps after autoloing:

  1. Add your USER to the group fuse:
    sudo adduser USER fuse
    For this to activate you have to log in again, the easiest way to do this is:
    su USER
  2. Mount your remote directory by adding this line to .bash_profile:
  3. If you ever have to unmount the directory you can do this with umount as root or with fusermount -u as a user.

Start remove mouse cursor and start slideshow after starting x:

  1. Add these lines to ~/.config/openbox/
    unclutter &
    feh --full-screen --randomize --auto-zoom --slideshow-delay 10 /home/makkan/images/ &

Disable screen blanking:

  1. First of all make sure the bios doesn't blank the screen.
  2. Add these two lines to .bash_profile:
    setterm -blank 0
    setterm -powersave off
  3. Edit /etc/console-tools/config
    Change this line: BLANK_TIME=30
    To: BLANK_TIME=0
  4. In your ~/.config/openbox/ add these lines:
    xset -dpms &
    xset s off &
    xset s noblank &

Reduce disk writes

  1. If you have to use swap to get things working set it to minimal use by editing: /etc/sysctl.conf
    Add the line: vm.swappiness=0
  2. In /etc/sysctl.conf also activate laptop mode by adding the line:
  3. Activate your new configuration by typing: sudo sysctl -p
  4. Rsyslog writes a MARK every 20:th minute, disable this by editing /etc/default/rsyslog and set:
    Restart rsyslog with:
    sudo /etc/init.d/rsyslog restart
  5. Cron writes a report every hour/day/week and so forth. Disable this by editing:

Monday, April 13, 2009

Installing Linux on a Toshiba Satellite 320CDS

I've tried a wide range of Linux distributions on this old laptop, from Slackware to Ubuntu via DSL. But I finally settled with Debian. I've used Slackware since 3.X and I originally intended to use here aswell. However that was a couple of years ago and I had alot of issues with sound and the wireless. Then Ubuntu came along and sound and wireless worked without any problems at all. But Ubuntu is not really ideal to run on a 233MHz system with only 96 MB RAM. So I tried other variants of Ubuntu like: Xubuntu, Fluxbuntu and server installations of Ubuntu. However when I was looking for a good tutorial to do a minimal installation of Ubuntu I came across a good tutorial for Debian aswell.

The reason I tried Debian is because I had alot of trouble with Ubuntu dropping out to busybox while booting the installation CD. I temporarily solved that as described below but I got really tired of it aswell.

Load ide-generic on failed boot of an installation CD.
In busybox type: modprobe ide-generic
Press: CTRL-D to continue booting.

A similar problem might arise during the installation process. Ubuntu will fail to find your CD and ask to scan for it. Before scanning open up another terminal and load the module from there.

Load the ide-generic module on a running system.
Press ALT-FX to open up a free terminal. X= 1-4
Type: modprobe ide-generic
Now scan again for the CD.

On a final note, since this problem will persist until you do something about it. After your first successful boot, before you do anything else.

Load the ide-generic module on boot.
Type: sudo nano /etc/initramfs-tools/modules
Add the line: ide-generic
Save and quit.
Type: sudo update-initramfs -u

The above issues does not exist in Debian and like I said before, thats why I ulitmately went with Debian. To do a minimal install with Debian just follow the above link to the tutorial and you're set.

Other stuff worth mentioning.

Wireless: 3com Office Connect 11g PCIMCA card.
The card will be detected by the kernel while installing. But it won't start since the firmware is missing. The firmware can be aquired here.
There's a really good tutorial in the that describes how to set up a wireless card and have it working with WPA encryption from boot.
Sound: OPL3-SA2
Just run alsaconf and have it autodetect your soundcard.
Boot options: acpi=off, noapic, nolapic, vga=788
I use the above line, try to find out whats best for your setup.

One thing I should mention that might help anyone trying to find out the specs of a Toshiba laptop is that Toshiba still keeps the support site for ALL their models active.

Wednesday, March 18, 2009

Bring out the geek!

I'm a nerd or a geek I can't really be bothered to make a difference. This place will be my outlet for geekery and perhaps serve as a good place to find information if you ever need to do something I have already done.