Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Designing and building a keyboard (yager.io)
141 points by wyager on March 15, 2014 | hide | past | favorite | 58 comments


Related: a hardware hacker that I know recently designed and made a new keyboard[1], which looks really interesting and fun to make. Fortunately he also provided really good detailed instructions[1][2] so other people can make it too. I'm not at the skill stage yet where I can make it myself, but it'll probably be the first complex hardware project I eventually undertake.

[1]: https://github.com/technomancy/atreus [2]: http://technomancy.us/173


OOP in keyboard firmware? Am I the only one who finds this quite a lot more complex than it needs to be?

> The fact that I2C communication blocks immediately is important. Button debouncing is done by counting the number of "frames" for which a key is in a certain state.

The obvious solution for this is to synchronise the I2C clock to the matrix scanning loop, so you receive/send one bit each time through the loop. Even better, do away with the I2C overhead completely and use a continuous serial protocol between the two halves.


>OOP in keyboard firmware?

I could do it with FP if someone made a Haskell to AVR compiler :)

>Am I the only one who finds this quite a lot more complex than it needs to be?

What functionality would you propose stripping?

>The obvious solution for this is to synchronise the I2C clock to the matrix scanning loop, so you receive/send one bit each time through the loop.

That's the wrong solution. The main loop takes some milliseconds. Communication at that rate would be intolerably slow. And how is that any better than natively clocked I2C? I'd have to re-implement the entire protocol in software to get that kind of control.

>do away with the I2C overhead completely and use a continuous serial protocol between the two halves.

What overhead? Any overhead introduced by I2C is very minimal.

What benefit would a "continuous" (do you mean asynchronous?) serial protocol have? There are also a number of downsides: 1. It wouldn't work well with the symmetric halves design. The cable would have to switch the TX and RX lines, and no common cable does that. 2. It wouldn't support more than two keyboards at once, unless I implemented a shared-line serial protocol from scratch, and then why not just use I2C? And using an asynchronous serial protocol doesn't solve the board synchronization problem.

The new version of the board also breaks out the UART header for people who want to do exactly this, but the UART is not a better solution.


> What functionality would you propose stripping?

The complexity here is not in the functionality. It's in the design and implementation.

> The main loop takes some milliseconds.

The MCU has a 16MHz single-cycle core. That means a 62.5ns instruction cycle, or 16,000 instructions in 1ms. What makes it require >16,000 instructions every time through the loop?

> What benefit would a "continuous" (do you mean asynchronous?) serial protocol have?

I do mean a continuous one, with the master driving the clock at the frequency of the main loop, and the slave(s) synchronising their transmissions with it. One of the biggest advantages I see is that you can make use of unused positions in the key matrix, so that they can be scanned at the same time as all the others. You just need to know which one, and instead of applying debouncing/up/down, accumulate the bits of scancode that are sent in and pass them through.

> 1. It wouldn't work well with the symmetric halves design. The cable would have to switch the TX and RX lines, and no common cable does that.

GPIOs are bidirectional. You can do the crossover configuration entirely in software, since the current design already detects whether it's plugged in from USB.

> 2. It wouldn't support more than two keyboards at once

How would you do this with the current design? They're symmetrical, but I don't see any way to chain or hub them together (unless you use a USB hub to connect as many independently as you want...), so I think that's a bit of a moot point. But if you are thinking of a star topology for this "keyboard area network"(!), using another unused key position in the matrix of the master for more extension boards would work. Each board could act as a hub for more, but this quickly gets into "why would you ever want to do that" territory.

> unless I implemented a shared-line serial protocol from scratch, and then why not just use I2C?

Because I2C was defined with different assumptions in mind.


>The complexity here is not in the functionality. It's in the design and implementation.

I'd love to hear some proposals for simplifying the implementation.

>What makes it require >16,000 instructions every time through the loop?

Mostly USB library stuff, I think. Been a while since I profiled it.

>I do mean a continuous one...

Can you further explain this paragraph? I don't know what you mean by "unused positions in the key matrix".

>You can do the crossover configuration entirely in software

Like I said: I'd have no implement the protocol from scratch, in software. The hardware UART does not support this functionality.

>How would you do this with the current design?

You can splice a TRRS cable or buy a TRRS splitter. The new version of the board actually has a dual-jack USB-A connector to make daisy-chaining even easier.

Again, not sure what you mean by "unused key position in the matrix".

>Because I2C was defined with different assumptions in mind.

Which were?


> I'd love to hear some proposals for simplifying the implementation.

The one thing that stands out is that many of the classes only have one instance created, and they're classes that don't have much functionality in them. Returning structures from functions requires a copy, in this case the array of button states, and copies of them are also created inside of functions like ButtonDebouncer::update. Only one of these state arrays is ever needed, so make only one...

The actual matrix-scan loop in HardwareController could also be simplified greatly; this usually just involves shifting a 1 bit through the row/column driver output port register(s) and reading the input port(s). There's no need to turn all the rows/columns off each time, since getting the next col/row is only a matter of changing which one is being driven. Getting the button number shouldn't require a multiplication (I'll admit I was pretty shocked when I saw that!) either, since each iteration of the inner loop is the button after the previous one, so it can be done with one counter.

> Mostly USB library stuff, I think. Been a while since I profiled it.

I'm more familiar with PS/2 keyboard protocol which is much simpler, but USB shouldn't be that much more complex to send/receive info once everything has been initialised (and as I understand from working with USB controllers in non-keyboard devices, the SIE does much of the actual transfer work in hardware.)

> Can you further explain this paragraph? I don't know what you mean by "unused positions in the key matrix".

There can be row/column combinations which don't have keyswitches at their intersection, but are scanned anyway. You can connect other units so that they act like keyswitches when they send information.

> Like I said: I'd have no implement the protocol from scratch, in software. The hardware UART does not support this functionality.

Of course.

> Which were?

A non-continuous clock. Transfers that occur in small bursts instead of one continuous serial stream.

(I have studied the IBM keyboard firmware, and worked with one for an 8051-based controller before.)


>The one thing that stands out is that many of the classes only have one instance created,

To maintain proper levels of abstraction.

>Returning structures from functions requires a copy,

Which is extremely fast, simple, side-effect-free, and likely optimized away by RVO.

>The actual matrix-scan loop in HardwareController could also be simplified greatly;

Nothing you described would actually be an optimization. Turning off all the rows/columns takes 1 cycle.

>Getting the button number shouldn't require a multiplication

Nit-picking. This is fast and easy to read. I'm not going to worry about the few nanoseconds required for a multiplication.

That's also not an issue of "simplification"; it's just premature optimization.

>but USB shouldn't be that much more complex

PJRC wrote that library. Not sure what they do.

>There can be row/column combinations which don't have keyswitches at their intersection, but are scanned anyway. You can connect other units so that they act like keyswitches when they send information.

Why would I do that? Part of the design is that each individual board is responsible for translating button presses to USB keycode deltas. This allows for better distribution of responsibility, and also the boards can be connected in any configuration/order and maintain the same behavior.

>Transfers that occur in small bursts instead of one continuous serial stream.

What's the downside to this? The bursts occur way faster than human perception could hope to notice.

Besides, if you want to be pedantic, any serial protocol communicates in "bursts".


> To maintain proper levels of abstraction.

Abstraction is only a tool, a means to an end; not the end in itself.

> Which is extremely fast, simple, side-effect-free, and likely optimized away by RVO.

Copying is one of the fastest things a processor can do, but that's not a reason to do it unnecessarily, even if the compiler optimiser could simplify it.

> That's also not an issue of "simplification"; it's just premature optimization.

Really? I suppose that if you consider abstraction the ultimate goal, you might think that shorter, simpler code would be "premature optimization"...

> Part of the design is that each individual board is responsible for translating button presses to USB keycode deltas.

That functionality remains the same; the receiving board just collects each bit of the scancode and passes it through directly to the USB. The sending board is still the one doing the matrix scan and position-to-keycode translation. The receiving board is just a passthrough.

> What's the downside to this? The bursts occur way faster than human perception could hope to notice.

It adds complexity to the software, because it has to deal with start/stop conditions, etc.

> Besides, if you want to be pedantic, any serial protocol communicates in "bursts".

Not if the clock is continuous; once the receiver and sender are synchronised, the sender can e.g. keep transmitting 0 bytes when there is nothing to send, and keycodes (which are all nonzero) otherwise.


This is interesting.

I've been looking for a split ergonomic type mechanical keyboard, but I haven't found any. The author just went about building what I was looking for.


I can recommend the ErgoDox[0].

[0] http://ergodox.org/



It has one unacceptable flaw: staggered keys. http://loup-vaillant.fr/articles/better-keyboards


I used the Freestyle for several years. It's a lot more comfortable than any other sub-$100 boards I could find, but the rubber-dome key response is pretty lame compared to real mechanical switches. The horizontal staggering didn't bother me at the time, but now that I've switched to columnar staggering it drives me nuts every time I go back.


I have been using my Truly-Ergonomic for almost a year now. Zero complain :)


This is awesome, and makes me want to try building something similar. On a related note, can anyone recommend a good source for learning about PCB design?


Sparkfun (http://www.sparkfun.com) has some good tutorials. "Beginning Embedded Electronics" is a good place to start.

I personally got started with microcontrollers and digital electronics by reading "The Microcontroller Idea Book" by Jan Axelson. It's a bit dated, but very well-written, and for me it was the first time that hardware really "clicked". I still refer to it from time to time for ideas for interfacing I/O devices.


GeekHack has lots of resources and knowledgeable folks re: all aspects of keyboard building:

http://geekhack.org/index.php?board=117.0

I built my board (http://technomancy.us/173) primarily building on knowledge from geekhack.org and the #geekhack channel on freenode.


Of course I would add that if your goal is more to make a cool board than learn about pcbs, it's easier to skip the PCB entirely and just hand-wire the switch matrix yourself. PCBs make sense at a scale of 5+ but IMO just add extra overhead for a one-off design.


Was just thinking about designing a dream keyboard after the "look at my chair" and "what's your keyboard" threads here on HN.

Came up with the following requirements:

- Must be split into a left hand and a right hand.

- No wires! (since it largely defeats the first point)

- All the regular relative raised key/ergonomic issues.

- Mechanical, obviously.

- Since the point is essentially arbitrarily positioned keyboard hands for touch typing, there's little purpose in having the letters on the keys: they're no longer necessarily right in front of you to look at.

- Optional: can either free-stand successfully or have some various means to allow it to be mechanically attached to various things/surfaces/mechanisms: Say if i want to have a lazy-boy chair with each arm being one of the keyboards.

So get to work HN :P


There's the ErgoDox, a split keyboard which is essentially a DIY kit, but it's not wireless -- although the potential for setting that up has been discussed.


Anyone working on anything a little more non-standard like a modern DataHand?

http://en.wikipedia.org/wiki/DataHand



I had heard of this DataHand before but looking at the wikipedia picture I realized that the mapping was directly lifted from QWERTY. It seems such a waste to me to design a new input method and not try to make an optimized layout for it (since you'll have to relearn to type anyway...)


The layout and hardware are things that can be tackled separately and independently. The hardware isn't a waste if it works.


While mechanical switches are everywere, it's simply impossible to find decent and decently priced scissor-switches. Does anyone know where to find such for less than $1 each?


I have been trying to find these or something similar for my keyboard project, but I haven't had any luck yet.

I don't know if it's a personal bias after using a Thinkpad keyboard over the years, but I feel like scissors switches don't put as much stress on my hands and require less effort.


How about buying a replacement Thinkpad keyboard and getting the switches from it?

I've used a Thinkpad as well as other laptop's keyboards over the years, and the Thinkpad ones usually do feel a bit more solid and accurate. They're still a bit too stiff for me, however, as my regular desktop's keyboard is an extremely soft rubber dome one (~40g actuation force). I've tried clicky keyboards, but never really liked them. It's definitely a personal preference.


I'd like to do that. The only problem is the switches are mounted on a custom plate. Fabricating a new plate isn't trivial because of tight tolerances. I haven't found any examples of someone who has taken on such a project as well.

What keyboard do you use?


Here's another take on a custom keyboard: http://blog.keyboard.io/


The website is already half dead, the pictures won't load here. Unfortunately without the pictures it's a bit harder to follow...


Here it is the whole post as a single pic: https://www.dropbox.com/s/hvng9q9rnk6vkfx/keyboard.png?dl=1


Oops! I totally underestimated the amount of traffic I might get from HN... should be working now!


This is a great article. Funny enough I'm seeing more and more of these detailed build your own keyboard articles these days. I don't know much about DIY hardware, has the market recently shifted such that making these things is much cheaper/easier than a few years ago?


Mechanical keyboards have been on the rise again, and that includes hardware enthusiasts who love to build! I enjoy taking care of my mechanical keyboards and admire others' collections. The growth here and in other areas like the RasPi has led to much more smaller production related to these markets and enabled communities to design their own hardware.


For me, it was the increasing accessibility and decreasing cost of custom made PCBs.


I always wanted to see someone make a proper attempt at a keyboard for "neutral" hand position. hands placed palm down are flexed "pronate", palm up "supinated", palms facing each other "neutal" is the most relaxed (face it: we're 'meant' to be holding our hands out ready to strangle each other) so i want a keyboard not rotated-up slightly, i want one built into a proper cone (apex up), or two cones (yes yes... i'm sure a couple of breasts might come to some of your filthy minds)


There have been some (shockingly expensive) keyboards in that format. I thought they were from Kinesis or Maltron, but I can't find them on either company's website atm. There are also ergonomic steno keyboards which can be placed in that configuration http://geminiwriter.com/ProductdetailsV1.aspx?ID=24


Great! I'm now tempted to build something similar but perhaps with Bluetooth instead.

Does the fact that the keys aren't staggered make it significantly better or worse to type on?


>Does the fact that the keys aren't staggered make it significantly better or worse to type on?

Depends who you ask! Personally, I think it's a bit more comfortable to type on than a staggered layout.

Some people love the matrix layout. Some people are rather put off by it.


I haven't used a non-staggered matrix layout, only column-staggered and row-staggered. Staggering the columns[1] makes allowances for the fact that your fingers are different lengths, and I like it a lot even though it takes a while to get used to. I suspect I would like a non-staggered layout better than row-staggering though.

[1] - like the Ergodox or my own Atreus design does: https://secure.flickr.com/photos/technomancy/tags/atreus


Sweet keyboard! It feels like it's missing a whole row of keys though.


Thanks. I intentionally kept the size small since it's not meant to be used as my primary board; I use an Ergodox when I'm at my desk and only use the Atreus when I'm out at coffee shops or relaxing on the couch, so the context is different. Using the fn key for so much definitely takes getting used to though.



More than a physical keyboard, a keyboard designed for mobile users excites me more.

Many people use one hand to type on the mobile phone (thumb to be more exact). However, the design of the keyboard on the mobile screen does not align well with the natural movement of the thumb. It is painful and hideous.

I believe an Arc keyboard on the mobile screen would be the best design. Anyone working on something similar?


The Twiddler3 https://plus.google.com/105804767481830727070/posts/j4M9fmRr... will be a physical keyboard suitable for mobile users. If you want a software keyboard then ASETNIOP http://asetniop.com/ looks fairly promising, but it's probably only suitable for large tablet-size screens and hasn't been released yet.


UM PCs had arcs at each side of the screen. They called it "dial keys". http://www.lunchoverip.com/2006/03/say_umpc.html

Sadly keyboards are often blocked by patents.


Have you seen the minuum keyboard? It looks really nice for very small screens.


Am I truly that alone in not liking split keyboards? I can certainly use one, if I have to. I much prefer the standard flat keyboard, though.

Of course, I confess that I have been lucky enough to never have any problems from one. I fully understand those that need it for medical reasons. I just don't know as that I would choose it if I didn't need it. (Rather, I know I would not.)


This is awesome... I've wanted my "perfect" keyboard for a long time. Maybe it might be worth trying to make.


Very nice job. Have you thought about an enclosure for it yet? This has always been the hardest part of PCB designs for me. PCBs are easy and cheap and there are lots of standard box-type enclosures but you either end up hacking holes in the sides with a Dremel or forgoing the enclosure entirely.


That's one of the greatest use cases for 3D printers! Whether ordering from Shapeways or printing on your own, making custom cases for projects is pretty awesome.


Unless you own your own, renting 3D printer time is crazy expensive for building a case for something this big. Laser-cut acrylic is faster, cheaper, stronger, and more precise.


I just put some little rubber feet on the bottom of the PCB and called it a day. It's small, cheap, and cool looking.

On the back side of the circuit board, there are 6 thermally isolated solder pads. I put them there so that I could potentially solder nuts to each of the pads, and then bolt the PCB to a case.


Great read, it is very interesting reading about the process you followed designing and building a hardware project from scratch.

Hopefully this encourages more people to have a shot at building something interesting, and write about it.

Thanks a lot.


The keyboard market makes me wonder if there would be a market for custom pcbs in customs shapes instead of just flat, or possible a 3D printer that can deposit both a polymer and conductive traces.


Non-flat PCBs would be a massive hassle to solder components to; normal pick-and-place+reflow is out of the question as the components would fall off, so you'd have to resort to gluing them on or soldering one leg manually.

Flexible (polyamide) PCBs are already available, with FR4 stiffeners where components are to be soldered. You could assemble one flat, bend to desired shape and attach to a form.


Nice work - very tidy and professional-looking. Thanks for sharing.


WOW! Last week I was on forums checking out about coverting a rubber dome keyboard to mechanical...

Now you got me thinking!!! :D




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: