DIY keyboards (and how keyboards work)

I’ve been pondering simple input methods for microcontrollers. One obvious idea is, a keyboard! But for some reason, my USB keyboards use a staggering amount of power compared to my microcontrollers–1W of power for my mechanical keyboards, maybe 0.1W for the regular ones.

Let’s look inside a commercial keyboard, and see if we can hook up to it:

a photograph of the interior of a commercial keyboard. there is a PCB, with two layers of flexible conductor on top, all clamped down

Yikes. What’s going on? Well, let’s make our own little keyboard, and explore what’s going on. We’ll build it in three layers, or “index cards”:

The bottom layer has 6 vertical stripes. The top layer has 3 horizontal stripes. Each place they cross will be a “key” you can press.

In between them, we add a spacer layer (punched holes) so they keys are “up” by default, and you have to press them to make them connect.

This picture might help explain how they will go together:

Now we assemble:

The final keyboard has 6 x 3 = 18 “keys”. We write the hex digits plus a couple extra keys with marker.

If I attach alligator clips to the second horizontal screw terminal, and fourth vertical screw terminals, and wire a battery and buzzer with the terminals, I get a connection beep only when I press the key “A”:

Two terminals with alligator clips attached to row and column terminals, and a screwdriver pointing at the "A" key addressed.

In a real computer, we obviously can’t just move alligator clips around. Instead, we attach wires to all 9 posts–three outputs wires for the horizontal lines, and six inputs for the vertical lines. We output a signal on the first horizontal line, and see if we can read it from any of the six vertical lines inputs. Then we output a signal on the second horizontal line, and see if we can read it, and so on for the third. Assuming only one key is pressed (or none), we can identify the key. This “scanning” process could be done thousands of times a second, rapidly enough that it can’t miss our slowpoke human fingers.

Click to view interactive schematic (credit: Kragen)
Click to view interactive schematic (credit: Kragen)

And this is how most keyboards work. There are some special keys–Shift, Ctrl, Alt, etc might be on their very own line, since we want to detect key combos. And better keyboards can detect multiple keys being pressed at once (N-key rollover), which I think they do by having a completely separate wire to each key which multiple people tell me they do with a diode next to each key.

For the above project, I used:

  • Three index cards
  • A hole punch
  • Scissors
  • A ruler
  • A pen (NOT a pencil, since graphite is conductive)
  • 9 screws, 9 nuts, and 18 washes. I selected #6 American Wire Gauge, which is about 4mm thickness
  • Copper tape

Did this work perfectly? Definitely not.

  • On some keyboards I’ve made, you have to press quite hard.
  • My multimeter takes a while to register a press. I think a microcontroller would be better.
  • You have to attach the terminals carefully. I think what’s going on is that you can actually put the screw exactly through the center of the washer which is actually making contact with the strips, so that only the washer is attached, and the screw doesn’t rub against the washer.
  • It’s of course fairly easy to mis-align anything. This is pretty easy to fix with care. I used the “spacer” grid to draw the centerpoint of the printed letters.
  • The screw heads are a bit thick, so it’s hard to press the keys in the column/row next to the screws. A piece of backing cardboard might fix this.

This was my third attempt. Here’s the second, using aluminium foil. It worked at least as well, maybe better, but it was harder to make. I just taped the foil down, taking care not to cover the contact points. I am told the aluminium will gradually oxidize, making it non-conductive.

And here’s one using graphite from drawing hard with a #2 pencil.. Graphite, it turns out, works terribly, and I couldn’t read a signal halfway down the index card. Despite what people have told me, I’m not yet convinced you can make a conductive wire out of it.

Tagged , ,

Controlling a computercraft turtle remotely

Screen Shot 2015-10-18 at 7.16.59 PM
Screen Shot 2015-10-18 at 7.17.30 PM

  1. Install Redis: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-redis
  2. Install Webdis
  3. Start a minecraft server with computercraft. You will need to have the http API enabled, which is the default.
  4. Put down a turtle I recommend a turtle with a crafting square and a pickaxe. I also recommend giving it a label. If you’re not trying the turtle replication challenge, either disable fuel or get a fair bit of starting fuel. Write down the computer’s id.
  5. Put down a chunk loader, if you’re in a modpack that has them, or DON’T log out. Computers and turtles can’t operate unless the chunks are loaded. If you’re putting down a chunkloader, I surrounded them with bedrock for foolproofing.
  6. Open the turtle and download the following script, changing “redis.example.com” to your own redis instance: pastebin get 8FjggG9w startup
    After you have the script saved as ‘startup’, run it or reboot the computer, and it should start listening for instructions.

    redis = "http://redis.example.com" 
    queue = "sshbot" .. os.getComputerID()
    return_queue = queue .. "_return"
    print("Remote webdis queues on icyego: " .. queue .. " and " .. return_queue)
    print("Receiving remote commands.")
    
    function exec(str)
      print("Running: " .. str)
      f = fs.open("tmp", "w")
      f.write(str)
      f.close()
      p = loadfile("tmp")
     status, err = pcall(function () p = loadfile("tmp"); return p() end)
      if status then
        status, ret = pcall(function() return textutils.serialize(err) end)
        if status then
          result = ret
        else
          result = ""
        end
      else
        result = "Error: " .. err
      end
      print(result)
      return result
    end
    
    print("Now receiving remote commands.")
    while true do
      handle = http.get(redis .. "/BRPOP/" .. queue .. "/5.txt")
      if (handle and handle.getResponseCode() == 200) then 
        str = handle.readAll()
        handle.close()
        str = string.sub(str, string.len(queue) + 1)
        result = exec(str)
        if string.find(result, "Error: ") then
          result2 = exec("return " .. str)
          if string.find(result2, "Error: ") then a=0 else result=result2 end
        end
        http.post(redis, "LPUSH/" .. return_queue .. "/" .. result)
      end
    end
    
  7. On your local machine, save the following, again replacing “redis.example.com”:

    #!/bin/bash
    function send() {
      curl -s -X POST -d "LPUSH/sshbot${1}/${2}" "http://redis.example.com" >/dev/null
    
    }
    
    function get() {
      curl -s -X GET "http://redis.example.com/BRPOP/sshbot${1}_return/20.json" | jq .BRPOP[1]
    }
    
    if [ $# -ne 1 ]; then
      echo "Usage: rlwrap ./sshbot <COMPUTER_ID>"
      exit 1
    fi
    ID=$1
    
    while read LINE; do
      send ${ID} "$LINE"
      get ${ID}
    done
    
  8. Run: rlwrap ./sshbot , where is the turtle’s ID. You should be able to send commands to the computer now.

Tagged , ,

Money orders

A postal money order
A postal money order

Allow me to introduce you all to the postal money order. For $1.50, you can get the equivalent of a cashier’s check from the post office. It can only be cashed by whoever you make it out to, and it’s basically accepted as cash by every corporation. You can also just give someone a blank one, although that’s riskier to carry around for the obvious reasons.

I was tired of checks bouncing. I can’t be bothered to make sure my account remains such-and-such, which means it happens sometimes, especially times like now when I’m poor. So I asked my landlord if I could pay by money order–he’d never heard of them before, but seemed okay with it when I explained (he’s a really good guy!).

I went down to the bank and got out $2750, and headed to the post office. I asked for 9 money orders, each for $303. The postal worker really only made a couple funny faces about me being weird, although my friend said she was pretty loud about my walking out with that much cash-equivalent, it went pretty well. And I immediately endorsed all the money orders so now they can lie around the hose safely.

Also, they come with attachable receipts (shown in the picture) in case you lose the check and need a replacement, so that’s nice.

Tagged ,

The Bible, translated to the new latin

Abbot: I will perform the opening prayer in the New Latin. Oh ordlay, ivethgay usway ouryay essingsblay. Amen-ay!

Crowd: AMEN-AY!

Robin Hood: Men In Tights

In honor of National Novel Writing/Generating Month and Christmas spirit, I translated the King James Bible into the “New Latin” (aka Pig Latin).

1:1 Inway ethay eginningbay Odgay eatedcray ethay eavenhay andway ethay earthway.

1:2 Andway ethay earthway asway ithoutway ormfay, andway oidvay; andway arknessday asway uponway ethay acefay ofway ethay eepday. Andway ethay Iritspay ofway Odgay ovedmay uponway ethay acefay ofway ethay atersway.

-Ethay Iblebay

The full bible translation is here. Source code is here.

Tagged , ,