Wishful Coding

Didn't you ever wish your
computer understood you?

RCX Plotter with Glidewheel

I modified the UBS plotter model to work with the NXT using 2 glidewheels and a normal converter between NXT and classic LEGO connectors.

The original model has two spoke wheels with touch sensors on them, to count the rotations. I replaced these with glidewheels.

Since the UBS is modular, it should be fairly simple to power other models with the same glidewheel-enhanced modules.

I also slightly modified the compressor gear train and paper feed to be more reliable with my old LEGO. Other than that, the model is completely original.

For a nice introduction to the original model, I refer you to Henrik Bækdahl.

Mindsensors Glidewheel

I just got two Glidewheels from Mindsensors for testing. The Glidewheel allows you to integrate other motors into your NXT models, providing precise control over even the oldest 9V motors.

The Glidewheel is designed for Power Functions motors, but works just as well for my RCX motors.

The hard part of using them with RCX LEGO is that they don’t fit directly or close to the RCX motors. You’ll have to mount them elsewhere and stick an axle through them. This is further complicated by the stud-based RCX LEGO.

The first thing I made with them is this small car that uses a drive and steer motor. Even with the rotation sensor that you could buy for the RCX, it was incredibly hard to steer a robot like this.

With the Glidewheel it is incredibly easy. Well, almost. My first attempt looked much like my past attempts with the RCX.

The RCX motors are a lot faster than the NXT motors, so what happens is that the PID controller in the NXT starts overreacting.

To stop this, I used an algorithm called gradual descent(or twiddle, as prof Thrun calls it), which basically modifies P, I or D a little, and sees if it gets better or worse.

float pid[];
float delta[];
int err;
int newerr;
mutex running;

task record() {
	newerr = 0;
	int tacho;
	Acquire(running);
	for(int i=0; i<200; i++) {
		tacho = MotorRotationCount(OUT_A);
		newerr += abs(tacho - 365);
		Wait(10);
	}
	Release(running);
}

inline void run() {
	ResetRotationCount(OUT_A);
	start record;
	RotateMotorPID(OUT_A, 100, 365, pid[0], pid[1], pid[2]);
	Acquire(running);
	printf("%d", newerr)
	Release(running);
}


task main() {
	ArrayInit(pid, 32, 3);
	ArrayInit(delta, 5, 3);
	err = INT_MAX;
	run();
	while(ArraySum(delta, NA, NA) > 0.1) {
		NumOut(0, LCD_LINE2, pid[0]);
		NumOut(0, LCD_LINE3, pid[1]);
		NumOut(0, LCD_LINE4, pid[2]);
		for(int i=0; i<3; i++) {
			pid[i] += delta[i];
			run();
			if(newerr < err) {
				err = newerr;
				delta[i] *= 1.1;
			} else {
				pid[i] -= 2*delta[i];
				run();
				if(newerr < err) {
					err = newerr;
					delta[i] *= 1.1;
				} else {
					pid[i] += delta[i];
					delta *= 0.9;
				}
			}
		}
	}
	PlayTone(432,1000);
	Wait(10000);
}

</code>

The result of this code for my little car was

PID
Default963232
Free404032
Load403240

Inserting these values in my code, I get this smooth motion.

Code:

mutex inControl;

task avoid() {
	while(true) {
		while(SensorUS(IN_4)>30);
		Acquire(inControl);
		PosRegSetAngle(OUT_C, 90);
		OnRevRegPID(OUT_A, 50, OUT_REGMODE_SPEED, 40, 32, 40);
		Wait(2000);
		OnFwdRegPID(OUT_A, 50, OUT_REGMODE_SPEED, 40, 32, 40);
		Release(inControl);
	}
}

task turn() {
        while(true) {
                Wait(1000);
		Acquire(inControl);
                PosRegSetAngle(OUT_C, 90);
		Release(inControl);
                Wait(1000);
		Acquire(inControl);
                PosRegSetAngle(OUT_C, -90);
		Release(inControl);
                Wait(1000);
		Acquire(inControl);
                PosRegSetAngle(OUT_C, 0);
		Release(inControl);
        }       

}

task main() {
	SetSensorLowspeed(IN_4);
        OnFwdRegPID(OUT_A, 50, OUT_REGMODE_SPEED, 40, 32, 40);
        PosRegEnable(OUT_C, 40, 40, 32);
	Precedes(turn, avoid);
}

</code>

Published on

Linux Time Machine Backup with netatalk 3.0

There are quite a few lengthy guides on how to back up your Mac to a Linux box with Time Machine and netatalk 2.x.

You don’t need any of that. With netatalk 3.0, it is a single line in your config file, time machine = yes, and you don’t even need to set TMShowUnsupportedNetworkVolumes.

On Arch Linux, all you need to do is

  • pacman -S netatalk
  • Append dbus avahi-daemon netatalk to your DAEMONS in /etc/rc.conf.
  • Add your backup folder to /etc/afp.conf like so:

    [ShareName]
    path = /path/to/backup/drive
    time machine = yes
    

Now start the daemons and you’re good to go. Even Bonjour is taken care of automatically.

On Ubuntu, netatalk is still at version 2, so you’ll need to compile it from source. Make sure you install Avahi.