George Bryant

Making a DIY pointing stick

As an input method, pointing sticks are pretty uncommon. They’re familiar to users of ThinkPads and some Dell or HP laptops, but most other people haven’t come across them. The pointing stick is the nub in the middle of the keyboard that you push around to control the pointer. It’s quite convenient to move the pointer without needing to move your hands off the keyboard.

The problem I wanted to solve is that they’re almost exclusively available on laptops. Only two companies make external keyboard with pointing sticks - Lenovo and Tex. Some people building their own keyboards want to integrate a pointing stick. Their only option is usually to buy an old ThinkPad keyboard and remove the Trackpoint. I’d like to make it easy for anyone to include a pointing stick in their keyboard design.

The best way I can see to do that is to create an open-source pointing stick module that anyone can use. There are some pointing stick modules available, but they seem to be old stock. If I create an open source design, any keyboard designer can include it in their keyboard. It can even be tweaked to meet their needs.

This post is a summary of my initial progress creating this module. Starting with off-the-shelf strain gauge amplifiers, I then design a custom PCB and build it into a keyboard. The final product in this post isn’t ready for production, but it’s a good first step.

How do they work?

What makes a pointing stick different to a joystick? In a (resistive) joystick, movement of the stick moves the wiper of a potentiometer - usually one for each axis. The voltage from the potentiometer is proportional to the position of the stick. In a pointing stick, the movement of the stick is much smaller. It stretches and compresses strain gauges. These strain gauges are resistors which vary when stretched or compressed. The changing resistance gets amplified and then measured by a microcontroller.

Comparison of joystick and pointing stick. The joystick has a potentiometer drawn over it,
              while the pointing stick has two resistors, one being stretched and the other compressed.
Joysticks usually move the wiper of a variable resistor as you move the stick, changing the voltage at the output. Pointing sticks instead stretch and compress resistors to change their resistance. There's still a voltage change at the output but it's a lot smaller.

You might think that this sounds complicated - why would we bother using this instead of a joystick? In a way we are - it’s just a very stiff joystick with a different way of sensing the movement. The key for me is that the stick barely moves. It makes a big difference to how it feels, making it much easier to position the pointer. You can make them much flatter than a joystick, which is why they’re used in keyboards.

Getting it working

To begin with, I needed to know if this project is even realistic. A good way to do that is to put together some off-the-shelf modules. If that works, then I can design a dedicated PCB.

Using some cheap BF350-3AA strain gauge amplifier modules, I did a first test. The mount for the strain gauges is 3D printed, with the gauges stuck on with superglue.

Close-up of a pointing stick prototype. It's got an outer ring for support, with a plus shape in the middle and a screw sticking up out of the centre. There are four strain gauges glued to the plus shape, with two of them wired to two amplifier PCBs with extremely tiny wires.
It worked! Adding a second gauge to each axis would help it perform better. It can cancel out temperature variations, and increase the signal-to-noise ratio.

These amplifier boards use an LM358 dual op-amp to amplify the signal. I used Big Clive’s technique of taking photos of the PCB and drawing on them to build up a schematic of the module.

Inkscape screenshot showing photo of the PCB, with green lines drawn on it where the traces are. Screenshot of the schematic. It's quite small but there's a bridge circuit and two operational amplifiers.
Here’s my reverse engineering method and the schematic I ended up with. Download my full schematic for the BF350-3AA module.

The amplifier circuit compares the voltage from the strain gauge voltage divider with another fixed one. It amplifies the difference between them by 47x. That voltage is then compared with one set by the tuning potentiometer, then amplified again by 24.5x.

There were a few interesting things about the amplifier:

Designing a PCB

The amplifier design was simple, but it seemed like I could optimise it for the pointing stick. Why use two stages of amplification, when one would do? If I could adjust the reference voltage from a microcontroller, there would be no need for manual tuning.

It turns out that’s exactly what digital potentiometers are for. I breadboarded a circuit using a MCP4251 digital pot to generate a reference voltage. The microcontroller can communicate with the MCP4251 to adjust the voltage.

A mess of wires on a breadboard, with the pointing stick prototype on one side and an Arduino on another
Here’s what the circuit looked like. The MCP4251 has 128 steps in its electronic “wiper”. This means the microcontroller can set the voltage anywhere between 1.128V and 1.368V. That should be enough to offset any off-centreness of the strain gauges. It worked pretty well! Now I could get a good idea how it felt to use the pointing stick.

For once I’d actually done the work of testing all the components for a PCB before designing it! The breadboard had served its purpose, but it was very fragile - there were a few connections that could be knocked out of place far too easily. It was pretty simple to put together a schematic of what I’d built on the breadboard. I did a rough (not very good) layout and sent it off to JLCPCB for manufacture.

Top level of the pointing stick schematic, showing connections between different sections of the design PCB layout of the pointing stick. There's a cheeky little 'Hello there!' underneath where the microcontroller will sit.
This is a dev board, so there are a bunch of different options built in. You can read the voltage from the strain gauge amplifier, or talk to the microcontroller over i2c. There’s a jumper to use 2.5V as an analog reference for more precision in ADC readings. The opamp has a little resistor network for feedback, so you can finetune its value.

It wasn’t long before the PCBs arrived. I quickly soldered one up, realised it was a pain (especially the MicroUSB connector), and bought a hot air soldering station. The second board was a lot easier to assemble!

Photo of my assembled pointing stick PCB Pointing stick PCB wired up to a pointing stick prototype. Much neater than the breadboard!
This was also the first time I used a hot air soldering station, and it was like magic! Admittedly, the leaded solder paste I accidentally bought may have helped with that.

Building it onto a PCB made the readings a lot more stable and less noisy (even though my layout was badly optimised for analog readings!). It was now feasible to plug it in and use it with a computer! It felt good, but without being part of a keyboard it was hard to tell how “right” it felt.

Building it in

This is the fun part - I was finally getting close to something I could actually use! The intention was to mount the pointing stick to the bottom of a keyboard and poke the stem through a hole in the PCB. Then, much like a ThinkPad keyboard, the nub could sit between the G and H keys. I had a couple of PCBs left over from my grid60 keyboard prototypes - perfect for drilling a hole in!

The location of the PCB hole marked roughly with sharpie, and precisely by scratching away the sharpie with calipers and a scriber. Two traces joined back up with tiny wires
I used the keys' centre holes in the PCB to locate the position for the hole. It did cut through two traces, so I needed to join them back up with a couple of mod wires.

With some components to avoid on the bottom side of the PCB, the mount for the strain gauges needed to make contact only in specific points. It also had to be as thin as possible, to avoid making the keyboard any taller than it needed to be.

Sketches of figuring out the geometry of the pointing stick
The tricky part I was trying to figure out here is how to get a flat enough surface to mount the strain gauges. I found that only the bottom layer from my 3D printer was flat enough. The slight ridges on the top layer were enough to make it hard to stick the strain gauge down. So I needed to design the part so that it had one flat side, without adding too much height to the keyboard. Designing some neat cable routing holes was also a consideration.
Strain gauges mounted to the 3D print and wired up, using tiny wires which connect to larger wires Underside of the strain gauge mount - it's fairly neat but there's a lot of hot glue holding wires in place.
This was actually the second design for the mount. The first one had to have bits ground away after printing to avoid components on the PCB. It’s wired to the strain gauges with very thin magnet wire to reduce the stress on the fragile pads.

Wiring up the strain gauges takes a long time! You have to be careful not to overheat them. They’re mounted on plastic, which can melt, and they can delaminate if you overheat them. I used the thinnest wire I had, to try to avoid pulling off the pads off the gauges. That thin wire then goes to a thicker, less fragile wire.

The whole keyboard, with a white pointing stick nub in the middle, and the PCB poking out the top edge Underside of the keyboard, showing the strain gauge mount hot glued to the PCB
Once assembled, it looked good! The keycaps surrounding the pointing stick needed the corners ground away to make room for it to move. Underneath it's a bit of a mess. Because of the added height it doesn't fit in the original case for the keyboard, so it's just mounted on bits of foam.

Trying it out

It was finally time to try out a keyboard with a homemade pointing stick built in. It actually worked surprisingly well! Using it to move the cursor around the screen felt quite natural, although setting the speed was tricky. At slow speeds it had good precision but took ages to get across the screen. At higher speeds, it was quick to cross the screen but lost the precision needed for selecting text.

The physical feel wasn’t quite like a typical TrackPoint pointing stick. It takes more movement to move the cursor at a similar speed. That’s due to the longer stem and flexible strain gauge mount, as well as my measurement PCB being less sensitive.

Lastly, I noticed that some noise in the ADC measurements caused the pointer to drift over time. This is sometimes a problem on commercial pointing sticks too - it’s because of the high level of amplification needed (and in my case, the bad shielding).

The X-axis opamp part of the schematic, with a smoothing capacitor, C14, added.
There was something that could be done about it though - adding a low pass filter. This meant adding a capacitor between the midpoint of the strain gauges and ground.

Adding this low pass filter to the PCB was simple, but in the process I broke the strain gauge for the Y axis. This was the second time I’d done that, and I decided to leave this prototype. The strain gauges and connections are way too fragile for this to be a robust solution.

Two graphs showing heatmaps of the X-axis values over time. The top one is with no low-pass filter installed, and has a spread mostly between -5 and 7 pixels. The bottom one is after the filter is installed and has a spread of maybe -3 to 3 pixels.
I could at least check the effect of the low-pass filter on the X axis. The graph above is a heatmap of the x-axis jitter over time with and without the low-pass filter. It reduced the noise by quite a lot (the colourful area is narrower), and didn’t have a noticeable impact on using it. That’s a success!

Going forward

When it works, this resistive strain gauge design works well! It’s quite nimble for text selection, and felt about as natural to use as my ThinkPad’s TrackPoint. The jitter in the pointer is mostly solved by the low pass filter, but it might still be present. I had some ideas for detecting and correcting the drift in software, but they turned out to be too aggressive and caused more drift than they removed!

The big problem with these strain gauges is that they’re fragile. It’s definitely not a design that would work for an actual product. It’s fiddly and time-consuming to connect, and not robust enough to mechanical stress. I wouldn’t recommend building this into your keyboard unless you really want to try it out!

There are a few things that are worth looking at in future iterations of this project:

This is a good first step towards an open-source pointing stick, but I’m going to leave the next one for another time. But speaking of open-source, here's the repository on Gitlab!