2019-06-13

Bluetooth trackball with all the electronics inside the ball

Update (2021-01-27): I have made an improved version of this project, see here for details.

For a while now I've been fascinated with the idea of making a trackball-type input device in which the ball itself would be the entire device. Unlike a regular trackball, where the ball is just a ball and registering its motion and communicating with the computer is done by external sensors and chips, here everything would live inside the ball. And now I have finally done it. Here's a video:

And here's how I did it. For obvious reasons, the device couldn't use USB, it had to be Bluetooth. For registering the rotation of the ball, a combination of an accelerometer and a gyroscope seemed like a good way of ensuring smooth results. I ended up using the following components:

I designed the ball itself in Fusion 360 and then 3D printed it. It has a diameter of 10 centimeters and consists of three parts, two halves of the ball and an inside part that holds the electronics and the battery. The three parts screw together to form the ball. I also made a stand on which the ball can be rolled, but that's just to make it easier to use as a trackball, the stand is optional and the device works when held in the air as well.

Here's what it looks like inside (the MPU-6050 is under the battery):

For the software part, I was pleasantly surprised when I found out that the MPU-6050 chip can do the sensor fusion magic (combining the outputs of the accelerometer and the gyro) for us and just give us the 3D orientation in the form of a quaternion. What's left then for the Arduino to do is to read the current orientation, calculate the difference between the previous orientation and the current one, translate it to X and Y mouse cursor offsets and send the appropriate commands to the Bluetooth chip that will pass them on to the computer.

Here's the Arduino code.

You may wonder how the ball knows which direction the cursor should go when it's rotated in a certain direction. The answer is of course that it doesn't, so the initial mapping of the directions might not be correct. But it does know which way is up (because it has an accelerometer), so the directions can be calibrated by rotating the ball around the vertical axis.

While I personally consider this project a great success, there's always room for improvement. For example, the trackball would be a little more practical if it had the ability to click, not just to move the cursor. I explored the idea of detecting taps on the ball using the accelerometer, but found it hard to eliminate false positives. This area needs some additional work.

An obvious shortcoming of the current solution is that to switch the device on or off, I have to unscrew the two halves and connect or disconnect the battery. Ideally there would be some way of doing that without disassembling the ball, a magnetic switch of some sort or maybe the device could always be on and just go to sleep when it's not used for a while (like regular wireless mice do).

On a related note it would be really cool if we also didn't have to open the ball to change the battery. Seems like a good use case for wireless charging.

If I ever do a next version of this, I will probably try to use a different Bluetooth board, one that's not discontinued (and perhaps can do Bluetooth LE).

2019-06-11

Time tracking wifi cube

There are many apps and websites for tracking time spent on projects and I'm sure they work well. But I like physical objects so I made a gadget - a cube that you can flip to a different face to indicate that you're now working on some project or task. Each face corresponds to a different project and one of the faces means you don't want to track time anymore. The idea is of course not original, there are similar commercial products available, but hey, this one's mine.


I had two design goals: first, I wanted the gadget to be standalone and not need a companion app on a phone or a computer. So it needs to have wifi and talk directly to the Internet. Second, I wanted the cube to last a long time on battery, at least a few months. So I had to learn a bit about how deep sleep modes work on microcontrollers.

Here's a video that shows the cube in action. (The laptop is just there to show that time reporting works, as I said the cube talks to the Internet directly.)



These are the parts that I used to make this happen:

  • ESP8266 board (Wemos D1 mini) for wifi
  • MPU-6050 accelerometer to check which side the cube is flipped to
  • SW-18010P vibration sensor for detecting motion
  • ATtiny85 chip for watching the vibration sensor and waking up the wifi chip
  • MCP1826 voltage regulator with a shutdown pin that made it easy to switch the wifi chip on and off

The idea here is that most of the time the ESP8266 chip is off and the ATtiny85 chip is in deep sleep, using almost no power from the battery. It is set to wake up when the state of one of its pins changes - a pin connected to the vibration sensor. Then the ATtiny85 chip enables the voltage regulator, waking up the ESP8266 chip, which reads the orientation of the cube from the accelerometer and makes a HTTP request to report it to a time tracking service. When it's done it signals the ATtiny85 chip on another pin. The ATtiny85 then disables the voltage regulator and goes back to sleep, waiting for another interrupt on the vibration sensor pin. An LED indicates when the chips are awake.

Here's a schematic of the connections. You may notice an extra button, I will explain its purpose in a moment.


And here's the code: the part running on the ATtiny85 is done in Arduino and the ESP8266 part in MicroPython.

I used Toggl for tracking time, but any service with a reasonable API could be used, the cube just makes HTTP requests.

Since the cube is woken up by motion, we have to consider what happens when you put it in a bag and take it with you. We don't want it to wake up constantly and deplete the battery. So here's how it works. The ESP8266 chip reads the accelerometer and waits for the readings to settle before making the HTTP request and signaling the ATtiny85 to go to sleep. So if the cube keeps moving, that signal never comes. And the ATtiny85 chip has a 30 second timeout. If it doesn't receive the signal before the timer runs out, it switches to "travel mode". Which means it goes back to sleep, but now it ignores the vibration sensor - it will only be woken up when the button is pressed. When it's pressed, it goes back to normal mode. That way we still get the long battery life, but we can take the cube with us.

Currently pressing the button is not very convenient as the cube needs to be opened up to access it.

Another improvement that comes to mind is making it work with multiple wifi networks. Currently it only remembers one, which makes it hard to use the same cube at, say, home and work.