Excavator

Today I spent some time building an excavator. I had to choose between controlling all parts of the arm and letting some parts move together mechanically.

I chose to do the former, which means I don’t have any motors left for the chassis, but can freely move all parts of the arm.

Maybe another NXT or RCX kit could serve as the base, which also needs 3 motors: 2 to drive and 1 for the rotating platform.

All NXT building instructions now free

I thought long and hard about this, as a lot of effort went into making these building instructions, but I concluded that I feel better about sharing them with as many people as possible than sharing them with a handful and making a few bucks.

So I’m happy to announce that all the instructions I made so far will be available for free. Go check them out.

I haven’t been writing a whole lot in the past months, but I feel some things breeding and I’m also super excited about the new EV3 coming out this year.

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);
}

The result of this code for my little car was

P I D
Default 96 32 32
Free 40 40 32
Load 40 32 40

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);
}

Face Tracking Laptop Crawler

First post from the US!

I can’t really do nice photography, video and building instructions here, but I did make a robot.

This thing sits under your laptop, and can drive it around and tilt the screen. The idea is that it will always face you, and keep a fixed distance too.

It uses the webcam of my laptop to track my face using OpenCV from Python.

It could also keep a fixed distance using the ultrasonic sensor, but this is not implemented.

NXT in-line skater

I found a video that features a skating robot, it moves, but skating? I did a lot of skating myself, so I started to think about a better skating movement.

It occurred to me that while skating around pylons, you don’t need to take your skates of the ground. What you do instead is hard to explain.

I tried to explain my idea to anyone who’d listen in #mindboards, but to no avail. You just have to see it with your own eyes.

It is a really fun thing to build and play around with. I suspect you can find more efficient and inexplicable ways to move and turn.

Get the building instructions for this model

This is the Mirah code I used in the video:

import lejos.nxt.Motor
import lejos.nxt.Button

def align()
	Motor.A.rotate(360 - (Motor.A.getTachoCount() % 360))
	Motor.C.rotate(360 - (Motor.C.getTachoCount() % 360))
end

speed = 150
Motor.A.setSpeed(speed)
Motor.C.setSpeed(speed)

Motor.A.forward()
Motor.C.forward()

Thread.sleep(20000)

Motor.A.stop()
Motor.C.stop()

align()

Motor.A.backward()
Motor.C.forward()

Thread.sleep(20000)

align()

Motor.A.forward()
Motor.C.forward()

Button.waitForAnyPress()

Mirah on the NXT

I’m working on a few things that require a bit more code that what I’ve done so far, but I find it to cumbersome to write so much code using NBC, NXC or NXT-G. Then I found Lejos.

Lejos is a Java Virtual Machine for the NXT, and it replaces the standard firmware. While Java is a marginally nicer language, the major win is in the packages.

Lejos comes with a lot of packages that contain useful code for doing common things, neatly organized by names like lejos.navigation.Navigator or java.util.Map.

The only problem with Java is that it’s verbose. Compare a simple program that prints “Hello world!” written in Ruby, and in Java.

You might wonder why Ruby is suddenly involved. It’s because of Mirah, which is Ruby syntax for Java classes. You could thus run the linked Ruby code, but you are actually using java.lang.System.out.println.

This means that if you need to know how to write something, google for the Ruby solution. If you want to know which classes to use, look for the Java solution. (classes are like hierarchical  collections of words, more on that later)

To make this all work with the NXT, you first need to instal Lejos.

To install Mirah, you also need to install jRuby, afterwards you can just run

jruby -S gem install mirah

Stay tuned for for some Mirah code for the NXT. I might also tell you more about classes.

Pneumatic Bug

So there you are. This is the result of a day or two of LEGO building, followed by weeks of thinking, sawing and soldering. Lucky for you, you don’t have to go through all that, and can just buy the needed parts.

This cute little bug can walk forwards, backwards and turn around, using 4 pumps on 3 switches. The outer 4 legs can move back and forth, with left and right having an individual pump. The middle legs are connected, and can move up and down.

By tilting the middle leg right, the outer right legs come of the ground, while the middle leg on the left is off the ground, then the outer legs can be repositioned for the next cycle.

There are touch sensors on the middle legs, to detect when they are of the ground.

To build this adorable model, you need your NXT, 4 pneumatic pumps, 1 compressor pump, 3 servo valves and a servo controller.

This is the walking routine in NBC for my custom controller. The concept is the same for the Mindsensors one.

#define tilt 0
#define left 1
#define right 2
#define servoport IN_2

thread main
SetSensorLowspeed(servoport)
OnFwd(OUT_A, 100)

loop:
servo(servoport, left, 150, result)
servo(servoport, right, 150, result)
servo(servoport, tilt, 100, result)
wait 7000

servo(servoport, tilt, 150, result)
servo(servoport, left, 100, result)
servo(servoport, right, 200, result)

wait 5000

servo(servoport, left, 150, result)
servo(servoport, right, 150, result)
servo(servoport, tilt, 200, result)
wait 7000

servo(servoport, tilt, 150, result)
servo(servoport, left, 200, result)
servo(servoport, right, 100, result)
wait 5000

jmp loop

endt

Download building instructions

DIY Servo Controller

This is another advanced home-made device, It took me weeks to do it. I was looking at the Mindsensors servo controller, when Matt Allen casually mentioned you could make them yourself. Once I set out to make one, I wanted it to do a little bit more.

I thought it would be nice if it could read input from an RC receiver as well. The final design has 2 readable inputs and 3 switchable ones, so you can directly control the servos.

Starting in the top-left corner, going clockwise, there is the PICAXE programmer header, 3 servo outputs, the servo battery connector, the NXT connector, 2 readable inputs and finally 3 switchable inputs. The PICAXE can directly control the outputs, or route them straight to the 3 non-readable inputs, for remote control.

If you know what you’re doing, this is the stripboard layout I designed. Use wisely, and at your own risk.

The code, more or less compatible with the Mindsensors quick mode.

#picaxe20x2
#no_data
'#define switching
setfreq m32

init:
table 0x00, ("V0.1")
table 0x08, ("pepijn")
table 0x10, ("servo")

for b20 = 0 to 0x17
	readtable b20, @ptrinc
next b20

symbol servin1 = w0
symbol servin2 = w1
symbol servpos = b4
symbol servpin = b5
symbol incontrol = b6

servo B.2,150
servo B.3,150
servo B.4,150
pullup %10100000
hi2csetup i2cslave, 0x02
setintflags %01000000,%01000000

main:
pulsin b.1, 1, servin1
pulsin b.0, 1, servin2
put 0x42, word servin1
put 0x44, word servin2

#ifdef switching
if servin1 < 1200 then
	incontrol = 1
	high C.4
	high C.3
	high C.2
else
	incontrol = 0
	low C.4
	low C.3
	low C.2
endif
#else
incontrol = 1
high C.4
high C.3
high C.2
#endif

goto main

interrupt:
setintflags %01000000,%01000000
hi2cflag = 0
if incontrol = 1 then
	get hi2clast, servpos
	let b20 = hi2clast - 0x5A
	lookup b20,(B.2,B.3,B.4),servpin
	servopos servpin,servpos
endif
return