Fitbit Versa Clock Face: Conway
My 2018 new year’s resolution was to learn difficult things.
I wanted to focus on learning things that are difficult to learn, push myself toward more facility with complex math and computer science. I’ve been spending a lot of time bashing my head against robotics, machine learning, and computer vision. It has been worthwhile and interesting. And hard.
But I needed a break. I wanted to learn something easy. Easy things are fun to learn, there is so much immediate progress. And, of course, easy for me is not easy for everyone. Arduino was easy for me but crocheting has not been (yes, I know you found it trivial and all I need to do is this than that then this again but, hey, look! An Arduino!).
I wanted to do something that didn’t involve brain-bending linear algebra, calculus, and 3D trigonometry. My husband (and Fitbit employee) Chris suggested I make a watch face for the Fitbit Versa that I stole from his work desk. I envisioned a jellyfish that lived on my wrist, softly drifting up (away from gravity). Perhaps my step count could influence the size (or number?) of the jellyfish.
He suggested something simpler. I decided that I’d have the time appear and then run Conway’s Game of Life on the pixels.
I went to dev.fitbit.com and logged in with Fitbit user credentials. They had examples, none of which were quite relevant but they were nice enough. I clicked over to Fitbit Studio, their development system, a web-based IDE. It had me create a new project, giving examples to start with. I based my new project on a clock face. I immediately wanted to see if it would run so I had to follow the steps in the Getting Started Guide. (Ok, Chris helped me through this but the guide actually gives you the steps in order.)
It was pretty fast to set up, easy to change background colors and plenty of examples. But then I wanted to read the pixels set by the time. Sadly, if that is possible, we couldn’t figure it out (Chris says it is not possible).
Giving up on the insurmountable problem, I went on to the next one. I wanted Conway’s Game of Life to run so I reviewed a few online versions written in JavaScript and found one that I liked from Andreas Kristiansen in Denmark. Since I could edit the code on the page, I played with it and verified I could understand and modify it.
In Fitbit Studio, in my resources/index.gui XML file, I added a whole bunch of rectangle objects. These were going to be my conway-pixels. This was a bit of a pain, listing them all but that is one use for Python (or Excel). Also, there might have been a better way, but listing them out one by one was the way I did it. I did eventually make their location on the screen programmatic, along with their height and width so they were square and non-overlapping, covering the screen in a grid.
With some tweaking and fussing, I got the Conway code running. It ran very, very, very slowly. Really slowly. (Of course, it ran fine in the easy-to-use simulator.) I commented out different parts of my code to figure out where the slowdown was: for loops. The Versa screen is 300x300 pixels. With my conway-pixels at 10x10 of the Versa’s pixels, I had a grid of 30x30 conway-pixels. The watch wasn’t happy with that. I switched from 900 conway-pixels to 100 conway-pixels and did some cheating/optimization of the algorithm so I only had to pass through the loop a single time. And it worked. Well, mostly worked: given some pixels on the screen it would play Conway's game of life.
The clock face still didn’t tell time. Giving up on the idea of reading the screen pixels, I decided to use my conway-pixels to show the time. I had some open source small fonts and small font handling code from a C project. I copied interesting parts and ported to JavaScript.
Before I go on, a few notes about JavaScript. I speak C almost as well as I speak English, some days better than I speak English. I speak C++ with a C accent but almost natively (assuming time stopped in 1998). I know a few other languages but the last one I learned and the one I’ve spent a lot of time in lately is Python. JavaScript looks a lot like C but your spelling mistakes will “compile” and only come out as it runs (or maybe never). Since JavaScript is new to me and Python is the last new language for me, I kept forgetting line ending semicolons. I think that is bad. I think you need semicolons but I’m not sure. On the other hand, things seem to work without all of them. Sometimes. Certainly, you can “compile” without them. Also, everything is a float? Or a string? I dunno?
Ok, that said, don’t read my JavaScript because… I have no idea what I’m doing. It isn’t pretty, I can tell you that much.
I got the fonts and font processing working. My fonts were 3 pixels wide and 5 pixels high, a little tight for a 10x10 conway-pixel screen. I made it work, almost legibly (but not really). Switching my rectangles to slightly overlapping circles gave me a retro-future look I liked.
The whole time I’m fussing with the code, I’m also testing, switching from my watch to the simulator and back again. That part was pretty easy. Well, it was pretty easy once I switched from the Build Output window to the Console output which showed me the runtime errors (so many typos!). And then I learned to used the console.log() for debug printing. Note: It was critical to use them sparingly when I was running on the watch, my system was slow enough just running Conway, adding printing did not help.
Eventually, I was happy with the way the time displayed and then dissolved into a Conway game using the time as the initial seed. I decided I was done enough to share it with Chris. I pressed Publish in Fitbit Studio which unexpectedly downloaded a file in my browser. A few minutes of searching in their forums led me to look on the Gallery Apps Manager site which seemed to take the file the Publish button downloaded. And then poof, I had a URL for my little Conway clock face.
It seemed like I was done. Of course, I wasn’t. There were bugs to fix and optimizations to do. Writing this up and cleaning up the code took more time than writing the initial version, probably because I found bugs and got irritated at the lagginess of trying to use other parts of my Versa. I found that the slowest part of my code was simply the for loops traversing the Conway cells. I’ve given up trying to fix it.
The Fitbit examples are good. Their documentation is ok… the information is there but difficult to understand except in retrospect. Their forums are awesome. If you don’t have your own Chris, maybe log into their Discord channel so you can get some hand-holding in the beginning.
There is so much more I could do with this (or you can, my code is open). My usual watch face updates the background with my steps/goal so I can see how close I am to my goal by how much of my watch face is blue vs. black. I could add heart rate or battery level on the face. I really should add a settings module so you can set your background to a color you like. I could put on a jellyfish that floats.
However, my goal was to learn how to make a Versa watch face. It wasn’t trivially easy but as I look at the trig and linear algebra I need to do to get to my next robotics lesson, well, it was pretty easy. Anything that takes less than ten-ish hours of learning seems sorta easy right now.