Wishful Coding

Didn't you ever wish your
computer understood you?

Thoughts about generating stripboard layouts

I am at the moment working on a servo controller for the LEGO NXT based on the PICAXE 20X21.

When you design a circuit, you usually use schematics like these:

schematic

However, when you actually want to solder the circuit, you either get a PCB, or you use stripboard, which looks like this:

stripboard

It is basically a board full of holes, with horizontal copper lanes connecting rows of holes.

All you have to do is insert the pieces so that things that should connect are on the same lane. To make things even easier, you can break lanes, or join lanes with a wire link.

Wait a moment… If we lay out the components like on the schematic, nothing will connect correctly!

Right, this brings me to the meat of this post. How can we automate this, to get an optimal and flawless translation from what is basically a graph, to a set of lanes?

I think the best tool for this job is constraint logic programming, of which cKanren is a neat implementation on top of MiniKanren.

Our program is somewhat related to the N-Queens problem, for which a solution is implemented in section 4.2 in the cKanren paper.

In he N-Queens problem, N queens must be arranged on an NxN board, so that no queen attacks another queen. This is implemented using all-difffd2, which forces the queens to all be on different rows, columns and diagonals.

Likewise, we can require our components to be all-difffd when it comes to lanes, but our situation is a little more complicated.

  • Components have multiple points which have constraints of themselves3
  • Lanes need to be broken under uC’s and might be broken for compactness.
  • Lanes might need to be joined with a wire link.

Let me state right away that I have not solved all of these complications, but I’ll let you in on my thought process.

For starters, lets define lanes as a finite domain of numbers. This allows us to use all-difffd, but gets us in trouble when we need to express broken lines.

(fresh (lane)
  (infd lane (range 0 50)))

In this simplified version, I also just defined components as a list of points they are connected to. Components that are connected, use the same fresh variable. This also gets us into trouble when we insert wire links.

> (run 1 (q)
    (fresh (l1 l2 l3 l4)
      (infd l1 l2 l3 l4 (range 0 10))
      (== q (list (list 'r1 l1 l2) (list 'r2 l3 l4) (list 'fet l1 l3 l2)))
      (distinctfd (list l1 l2 l3 l4))))
(((r1 0 1) (r2 2 3) (fet 0 2 1)))

The result is rather boring, as it just echoes back what is connected to what. It does get a little more interesting when we add constraints.

(define lanes (range 0 50))

(define lane
  (lambda (l)
    (infd l lanes)))

(define resistor
  (lambda (l1 l2 r)
    (fresh (l2+)
      (lane l1)
      (lane l2)
      (lane l2+)
      (plusfd l2 2 l2+)
      (<fd l2+ l1)
      (== r (list 'r l1 l2)))))

Now we can get some valid resistor positions, and incorporate their constraints into the full application.

> (run 5 (q) (fresh (l1 l2) (resistor l1 l2 q)))
((r 3 0) (r 4 0) (r 4 1) (r 5 0) (r 5 1))
> (run 1 (q)
    (fresh (l1 l2 l3 l4 r1 r2)
      (infd l1 l2 l3 l4 lanes)
      (resistor l1 l2 r1)
      (resistor l3 l4 r2)
      (== q (list r1 r2 (list 'fet l1 l3 l2)))
      (distinctfd (list l1 l2 l3 l4))))
(((r 3 0) (r 4 1) (fet 3 4 0)))

How to proceed from here? I don’t know. I think we need to find a different representation for lanes, to support breaking and joining them.

I started writing a goal called connectedo, to consider 2 lanes with a wire link between them as connected, but this is unfinished.

  1. COMPANY &LT;3 CAPS 

  2. Called distinctfd in the code on Github. 

  3. Such as “a resistor must span at least 4 holes” and “a uC has 2 continuous columns of pins with 2 columns between them” 

Chocolate dispenser

The latest in chocolate breaking technology! Using patented breaker technology, bar after bar is transported and broken off. No animals where harmed in the making of this robot.

My father eats a lot of chocolate, so the original idea for this robot was for it to keep track of and limit your chocolate eating. Unfortunately the NXT doesn’t keep track of the time, so you could just restart the program and eat more.

A solution to this problem would be to use the Mindsensors realtime clock, which costs $20, but since I have no intention to actually keep this robot around, I just used it as a dispenser for the weak and lazy.

Chocolate is fed into the back of the robot and is then transported to the front. A light sensor detects the foil and aligns the chocolate to the front edge. I keep the foil around the bar to make detection easy and to keep my LEGO clean.

When the button is pushed, one bar is extended over the edge and broken off by 2 NXT motors. Check the NBC code:

#define BLOCKWIDTH 100

dseg segment
  button byte
  light word
dseg ends

thread main
  SetSensorColorFull(IN_1)
  wait 100

  OnRev(OUT_A, 50)
NotThereYet:
  ReadSensor(IN_1,light)
  brcmp EQ, NotThereYet, light, INPUT_BLACKCOLOR

  Off(OUT_A)
  RotateMotor(OUT_A, 50, -100)

StandBy:
  GetButtonState(BTNCENTER, button)
  brtst EQ StandBy button

  RotateMotor(OUT_A, 50, -##BLOCKWIDTH)

  OnFwd(OUT_BC, 100)
  wait 1000
  OnRev(OUT_BC, 50)
  wait 1000
  Off(OUT_BC)

  jmp StandBy
endt

It took some time to calibrate the machine, but it was delicious. No extra parts are required for this robot, except some chocolate.

Download building instructions

Tower Crane

Picking up and carrying around stuff is fun, but another claw/gripper? Can’t we do something new?

That is what I did. I sat down with the idea of Pythagorean triangles in my mind, and then I imagined a tower crane, with all these diagonal truss beams. Djing!

So I started laying out triangles and piecing them together. I’m pretty content with the result, which uses 3 different triangles.

A few caveats:

  • You need a turntable, I didn't dare putting so much stress on a single axle.
  • The hook and winch are not in the manual, I used 3 different ones, and I bet you need another 3 for your own projects.

At first I used my gamepad code to control the crane, but later I programmed it as well.

Tower cranes are usually used to build high buildings right? It’s maybe not as cool as flying robot builders, but I managed to let my crane build a tower.

The logic goes something like “turn around until the ultrasonic sensor reads less than 20cm, pull the winch down and up, go to starting position, go down and up, repeat”, and can easily be programmed in NXT-G or NBC.

Before you buy, remember that you need a turntable and of course a bit of string. Both the old and new model turntables should work with minimal modifications.

Download building instructions