Upgrading a Giant Explore E+ 2 with the Rohloff Speedhub 500/14

The drivetrain side of my Giant Explore E+ 2 converted to the Rohloff Speedhub 500/14 from the Alki shoreline in West Seattle with the downtown Seattle skyline in the distance.
The brake side of my Giant Explore E+ 2 converted to the Rohloff Speedhub 500/14 from the Alki shoreline in West Seattle with the downtown Seattle skyline in the distance.

In September 2022, I got a 2022 Giant Explore E+ 2 GTS e-bike, which has been great (a more thorough review is possibly overdue), and I have put more than 2,000 miles on it in those few months. It’s a practical bike for my purposes: okay for road riding, gravel/dirt and light off-road, and of course has pretty robust electric assistance for Seattle’s hills and just general riding comfort. I’ve made a point to ride every day “rain or shine” so have put a lot of miles on it in the rain and snow, and I often tow a trailer full of tools for community cleanup projects.

One of my main complaints with the bike, though, has been the gearing. It comes with a 1×9 derailleur arrangement, using a microSHIFT CS-H093 11-42T cassette and a 42T chainring. In my experience, the 1st gear isn’t quite low enough for such a heavy bike in a hilly place (especially with a heavy rider and a trailer), and simultaneously, the 9th gear isn’t quite high enough for long slight descents or flats. I also don’t love having 9 gears on a derailleur with only a single chainring gear, with some of the most common gears I use (1-2 for hill climbing and 7-8-9 for cruising and descents) necessarily at fairly extreme chain angles.

For those practical reasons as well as for technical fun and aesthetic reasons, I thought it would be fun to upgrade the bike to an internal gear hub. After some research and especially checking compatibility as much as I could in advance, I settled on the Rohloff Speedhub 500/14.

Compatibility of the Speedhub

There are a few variations of the Speedhub, but most of them are not compatible due to one or more reasons. Once you work through the dizzying array of variations there are really only a few choices to be made for this upgrade:

  • Axle style: quick release or threaded
  • Number of spokes: 32 or 36
  • Color: silver, black, or red

I opted for quick release for drop-in compatibility with my current setup with trailer hitch, a 36-spoke wheel (more below), and given the dark blue and black color theme of the Giant Explore E+ 2, I went with black color to match. You’ll of course need the disc brake style, since the bike has disc brakes.

Choices in gearing

The bike comes stock with a 42T chainring, which I ended up keeping. The Speedhub allows you to easily change the input sprocket, and they sell sprockets from 13T to 21T, with the default being 16T. Between the choice of chainring and the Speedhub’s input sprocket, a lot of different gear ratios are possible.

Since I had already put a couple thousand miles on the bike with its stock gearing, I understood its current performance pretty well. I started by calculating the gear ratios of the stock bike with its 42T chainring and 11-42T cassette: 1.00 in 1st gear up to 3.82 in 9th gear. Since I was hoping to get one lower gear and one higher gear, I’d be aiming for the new 1st gear to be around maybe 0.9 or lower, and the new 14th gear around 4.2 or higher (at least 10% change for each).

With the default 16T input sprocket, the ratio of 1st gear would be 0.73 (27% lower than the old 1st) and 14th gear would be 3.85 (basically the same as the old 9th). After some spreadsheeting, I opted for a 14T input sprocket, which provides a new 1st gear ratio of 0.84 (16% lower than the old 1st) and the new14th gear would be 4.40 (15% higher than the old 9th). Sounds great! The remaining 12 gears also give a lot more intermediate steps than the old 7 gears.

This is what the comparison of the old vs. new gear systems looks like (graph made with R):

Graph of gear ratios of gears 1-9 on microSHIFT CS-H093 compared to the Rohloff Speedhub 500/14 with 14T input sprocket.

Note: The Speedhub documentation prohibits some gear ratios depending on bike and rider weight, to limit torque input. They provide a gear calculator which can be used to compare different chainring and sprocket combinations.


The bike comes with disc brakes, of course, and all we’ll really need to do is get the correct disc brake rotor for the Speedhub to be compatible with the existing brake calipers. My bike was built using a Tektro HD-M275 with a 180mm rotor of 1.8mm thickness, so I used the 180mm x 1.8mm Rohloff brake rotor, and it fits and operates perfectly.


Since the Speedhub uses a twist shifter it can’t be installed with the stock grips; it needs a shorter right grip to make space. I got the Ergon GP1 based on availability, but the GP2 or GP3 would likely be a better choice for the aesthetics of the bike (and I already miss the bar ends).

One compatibility issue: wheel speed sensor

Once I received the hub I was able to do a quick compatibility check to make sure there were no major issues.

Rohloff Speedhub, torque arm, and brake rotor test fit into the Giant Explore E+ 2 dropout with the derailleur still installed.

The stock bike uses a custom mounting location for the wheel speed sensor right next to the dropout on the left side of the bike, and uses a magnet mounted on the brake rotor to actuate it. Unfortunately that arrangement has two compatibility issues with the Speedhub:

  • The magnet is mounted to the rotor with a small carrier that expects the rotor to use the standard 6-hole mounting pattern, but Rohloff brake rotors use a 4-hole pattern with larger bolts. I knew this before getting all parts in, so I was expecting to need to do something about that, however, it didn’t end up mattering, because…
  • The sensor is mounted within range of the magnet on the mounting bolts on the brake rotor, which puts it very close to the dropout. The sensor itself has a clearance issue with the Speedhub (which is larger than most hubs), preventing the Speedhub from fitting into the dropouts at all unless the sensor is unmounted.

Not a big deal. The speed sensor is just a hall effect magnet sensor, it’s hermetically sealed, and it can pretty much go anywhere we can get a magnet to pass by it once per revolution of the wheel. There was enough slack in the sensor cable that I was able to move it back onto the chainstay, away from the dropout, and using a bit of custom shaped foam, I was able to mount it within range of a standard spoke magnet.

The speed sensor mounting location next to the dropout. A little too close, it turns out.
Speed sensor mounted on a bit of foam with zip ties, held in place with tape just to keep it from sliding on the chainstay.

I will probably custom design and 3D print a nicer looking and more permanent carrier for the sensor, but the foam part has been working nicely for me for a few hundred miles.

Building the wheel

The stock bike comes with 32-spoke Giant eX2 700c rims. Since I did this conversion at home and it was somewhat experimental (and might fail!), and I wanted to continue riding every day, I opted to build a completely new rim rather than re-use the current one. That way I could swap parts back to the derailleur at any time.

Since I would be buying all new parts, I could choose between the 32-hole and 36-hole Speedhub. I went for the 36-hole version partly due to availability, and partly because I felt like a 36-spoke wheel would be a better fit for my use: I’m heavy, the bike is heavy, and I tow heavy trailers. More spokes, more better. I also wanted to get a very sturdy/strong rim, and weight was not really a concern at all. Aesthetically, it should be black and not look terrible mixed with the stock rim on the front in case I want to keep that one.

I went with the Velocity Cliffhanger 700c 36-hole, disc brake, in black [from Northwest Bicycle]. I got Ritchey 700x19mm rim tape [from Northwest Bicycle].

The Speedhub documentation strongly suggested using specifically Sapim Race double-butted 2.0mm/1.8mm/2.0mm spokes [from Wheelbuilding Parts] and using the Speedhub documentation’s lookup table with the rim’s ERD I determined I would need 262mm length. Black, of course. I also got Sapim 12mm brass nipples to match.

After receiving all the parts, I built, tensioned, and trued the wheel myself with the fantastic assistance of Cory (@cyclegator) at the Center for Bicycle Repair on S Jackson. Rohloff specifies that only double (2x) cross lacing should be used, so that’s what we did.

Newly built wheel on a truing stand.

Be sure to check out Rohloff’s extensive documentation about wheel building for the Speedhub.


Since the Speedhub is technically “single gear”, you can use a single gear chain. They are supposed to be quieter and last longer due to having stiffer links since they don’t need to travel diagonally. I planned on keeping my old derailleur and its 9-speed chain ready to go in case something didn’t work, so I planned to get a new chain anyway. I chose the KMC e101, but due to a fulfillment error (which I didn’t notice until I was ready to install the chain) I received a completely different chain which was not compatible. Since everything was going well during my test fitting, I opted to shorten my old 9-speed chain instead. Although I received the new chain, I have been running just fine with the old 9-speed chain so far.

Installing everything

Installing the Speedhub was relatively easy for someone with moderate mechanical knowledge and ability. The instructions are excellent, although since they are generic to any bike, they are not very specific and require a bit of judgement. The build quality of everything from Rohloff is exceptional, and they provided a lot of spacers and extra hardware to ensure the installation should go well for almost any bike.

Installation in progress. You can actually see the incorrect chain I was sent in this photo. Oops.

This is the installation process I followed, more or less:

  1. Build the wheel with the new hub.
  2. Install the disc brake rotor on the hub.
  3. Install the torque arm on the hub.
  4. Remove the rear wheel.
  5. Unmount the tire from the old wheel and mount on the new wheel.
  6. Remove the chain completely.
  7. Remove the derailleur from the derailleur hanger, cut the cable end off, and remove the derailleur from the shifter cable.
  8. Remove the wheel speed sensor mounting screws and sensor cable retainer (leaving the sensor free to dangle out of the way)
  9. Install the chain tensioner on the derailleur hanger, using spacers as necessary to get the correct chain alignment.
  10. Loosen the disc brake caliper mounts to account for the slightly different position of the new brake rotor.
  11. Install the new wheel, shifting the brake calipers as necessary to align.
  12. Tighten the brake caliper mounts as necessary.
  13. Install the torque arm quick release on the chainstay using the provided instructions.
  14. Remove the old grips and shifter.
  15. Install the twist shifter and its control cables using the provided instructions.
  16. Route the control cables to the rear of the bike.
  17. Install the new grips, being careful to leave a bit of space between the shifter and the grip.
  18. Install the “external mech” box on the control cables, shortening the control cables if desired.
  19. Install the chain, shortening as necessary to achieve the correct tension.
  20. Fill the Speedhub with the provided oil.
  21. Adjust the adjustment screws for the control cables to achieve the tension you desire and make shifting feel good.
  22. Install the wheel speed sensor on the chainstay using an appropriate piece of foam or other material.
  23. Install the spoke magnet on a spoke in range of the wheel speed sensor and test that the speed is reported correctly.
  24. Cable manage and zip tie everything as desired.
  25. Done! Put the sticker on if desired.

Really not that bad, for such an impressive upgrade.

Issues and future improvements

I didn’t run into any issues of any substantial nature, actually (surprisingly). There are a few things that could be improved or which are not ideal. I’ll list them all here concisely:

  • The control cables are zip tied to the frame. I don’t mind the look, actually, and this is a work/practical bike rather than a show piece, but I may try to route them internally just for fun.
  • The control cables have an extra loop at the moment so that I have some extra length in case I want to route them internally, as above. If I decide not to route them internally, I should at least cut them shorter to remove the loop, which should improve the feel.
  • The wheel speed sensor is zip tied to a piece of foam. I intend to make a 3D printed part to hold it nicely and more permanently. When I do so, I’ll update to provide a link here.
  • I removed the derailleur, but not the shifter or shifter cable. The shifter is currently zip tied to the handlebars and out of the way, but I can remove it to clean things up even more.
  • The clearance between the 14T input sprocket and the chain tensioner mounted on the derailleur is very tight, and makes me think that with larger sprockets it actually wouldn’t be removable at all. I may look into whether it’s possible to get a slightly longer derailleur hanger to make wheel removal and installation a bit easier.

Parts list and prices

Speedhub 500/14 CC DB 36hRohloff68022$1,409.80
Speedhub rotor, 180mm x 1.8mmRohloff8287$89.00
Speedhub splined sprocket, 14TRohloff8542$21.00
Rim, Cliffhanger 700c, Disc, Black, 36hVelocity4000-62236$93.60
Rim Tape, 700 x 19mmRitchey48340847001$10.75
36 x Spoke, Race Double Butted, 262mm, BlackSapim$37.80
36 x Spoke Nipple, Brass 12mm, BlackSapim$7.92
Spoke Magnet for BDU2XX BDU3XXBosch2100160$14.66
Chain, e101KMCCN10226$40.51
Grips, GP1Ergon42410205$39.95


The bike runs and rides great! I have said that this is the gear system the bike should have had from the factory. Overall, I am very happy with the look and function of all aspects of the upgrade. It will be even better with a custom mount for the wheel speed sensor which would get rid of the only “bodge”. I may also attempt to route the control cables internally in the frame (and remove the shifter cable). In case I want to do that, I left an extra loop in the control cables to take up the extra slack rather than trimming them, but even so, shifting works fine and feels fine. I suspect it’ll feel even better once that loop is taken out.

The new 1st gear is especially great for towing a trailer uphill. I haven’t made much use of the new 14th gear, as often 12th or 13th is more then enough. In the future I may consider moving to a 15T or even 16T input sprocket to get an even lower 1st gear, but I am very happy with things as they are now.

Rohloff Speedhub and chain tensioner.
Rohloff Speedhub tension arm, “external mech” and control cables, and disc brake rotor.

If you attempt an upgrade/conversion and found this information useful, let me know!

I learned to read at 20 years old

[Note: I shared this post on Twitter and there has been a fair bit of discussion about it there. Please feel free to re-share if you find it interesting or you learned something, and I’m happy to answer questions or read your comments there, or in the blog post comments here, as well. Thanks for your support and kind words!]

If you’ve worked with me, read my technical writing, my public Twitter or Facebook posts, or read any of my posts here in the past, you would probably not consider me illiterate. (I hope, hah.) In fact you probably read the title of this post and thought it must be clickbait – but it’s not. It’s true. I was not able to read traditional books or anything else substantial until I was 20 years old.

I am dyslexic. I didn’t know it until adulthood.

In the past two decades I have worked in some exciting and incredible places and accomplished a lot. From small startups in the early days of the web, to being an early employee of and shaping the future of MySQL, moving to Silicon Valley to work at Yahoo!, running my own technical consulting company, expending inordinate blood, sweat, and tears to keep Twitter alive in its pivotal years, working in the heart of the beast at Google, and now helping the world’s entrepreneurs be successful at Shopify – I’ve been around a bit, and I’ve been incredibly lucky to have been given many opportunities to excel.

Disclaimer: This is my story, my situation. It’s deeply personal, of course, but due to human biology, and also human experiences, how dyslexia is experienced and dealt with varies a lot for everyone. Some of this probably applies to nearly everyone who is dyslexic, but no doubt some of it is my own quirks, or just wrong. I don’t really like writing about myself, and some of this is embarrassing to talk about publicly, but I am hopeful that this will help others struggling with dyslexia even if they don’t know it yet.

My insurmountable struggle with school

Growing up, my family moved a lot.

I was never in the same city, and thus the same school system, for more than a handful of years. I barely remember half of the schools I attended. I never had any long term relationships with any school staff or anyone that cared to understand what the reasons for my struggling actually were. Most of my teachers thought I was either lazy or stupid, or gave up on me. I was overweight, and in later years nerdy, and almost always (due to moving a lot) the “weird new kid”. I was bullied relentlessly by other kids.

Starting at a very young age, once I started in school, it was clear that something was wrong with me. I struggled with the most basic subjects in elementary school. I failed at, or failed to complete most of my work. It was a combination of struggling with the material itself (especially anything involving reading or writing), and boredom. I hated pretty much every single minute of school and did everything I could to avoid it. I was once (in third grade?) dragged inside the school–literally kicking and screaming–by the school principal.

I struggled through elementary and middle school, nearly failing several grades along the way. Then came high school, for which I was horribly unprepared, and I quickly realized I was in deep trouble.

Entering ninth grade, I attended a “year round” high school in Kentucky. This school had a quite unusual and somewhat experimental 4 x 90 minute daily schedule, which meant completing four full courses during the first half of the year, and starting an entirely new set of four courses after winter break. I did reasonably well.

Halfway through tenth grade, my family moved again, to another state, to a different school system – one which used a more traditional course schedule. Since we moved mid-year, this meant that I had completed half of my courses, but not yet started the other half, while the students I was joining at the new school were halfway done with all of their courses. Since the new school was in a different state, there were also slightly different credit requirements for graduation… leading to a very unpleasant school year of chaos.

Eleventh grade was a struggle as well, and afterwards, it was clear I was not going to graduate high school on time – I had failed two English courses, for one, so I would end up needing to take 10th, 11th, and 12th grade English all at the same time in my senior year, or repeat the 11th grade. I decided I had had enough. I dropped out of high school and took the GED test (after I moved states, on my own, to another state where it was legal for me to do so) to get a high school equivalent diploma.

I had planned to attend DeVry University and get a degree in Computer Science, but (long story short) it was not what I had hoped for. I struggled with depression (that I only now recognize), and I ended up attending only two semesters at DeVry before leaving and working full time instead. I’ve been working ever since.

Reading is not reading

How did I get all the way to nearly finishing high school–in the United States–while being functionally illiterate? There’s a lot to blame on the American school systems for that, and I won’t get into that here. However, one of the biggest challenges is that: reading is not reading per se.

All throughout school it would be hard to say, at any time, that I “couldn’t read”. I could read the instructions to problems, I could read aloud (mostly), I could read the board (untreated eyesight problems aside), and it would not have necessarily been obvious that, despite all of that, I could not read in the traditional sense: I could not read books, long articles, essays, etc. This meant that most academic knowledge was beyond my reach (and, to be honest, some still is).

It turns out that being “able to read” is not a singular thing where you either can or can’t – where you’re either literate or illiterate. It’s always been easy for me to read short passages, single sentences, instructions, short word problems, etc., but it was impossible for me to read books, long paragraphs, or anything really longer than half a page or so.

Writing is not writing, either. Throughout school, I really struggled with handwriting, producing only incredibly messy scribble with letters out of order, or backwards, and without space between words. To this day, unless I really concentrate on writing neatly, it’s the same.

I also struggled with math in school… especially with showing my work, rather than with understanding the math. I could not write well, but I innately understood the problems and the math behind them. I tended towards doing calculations entirely in my head, or writing scribbled “notes” (to offload my short term memory) rather than full solutions. I often used non-traditional ways of working out problems. (This is still how I do a lot of math.)

I learned that there is nothing that irritates an American math teacher more than not showing your work in the way they want you to. It doesn’t matter if you get the right answer. It didn’t matter whether I was excited about learning it.

Through much of my school years I mostly believed my teachers: I must be really lazy, or stupid. Something must be wrong with me.

A fortuitous parallel thread in my life: computers

As you are probably aware by now (or if you know me at all), I got involved in computers very early in my life, as well as (luckily) fairly early in the life of computing itself. I was 8 years old when we got my first computer in 1989: a yard sale IBM PCjr for $100, ostensibly for the family. When we got it, it was already quite outdated and limited (having been sold new about five years earlier). It came with IBM PC DOS (of course), cartridge BASIC, and most critically, the whole collection of original manuals.

Computer, operating system, and programming language documentation is somewhat unique: It tends to be composed of small fragments, each describing a single device, program, command, function, etc. Reading them, I realized very quickly that I could read just fine, and comprehend them. (In fact, I really understood them very well even for my age, and could visualize the way things worked spatially–due to dyslexia–but I didn’t know that yet.) Using the results of what I learned from those manuals, I also discovered that I really enjoyed making the computer do what I wanted.

Having full-time access to a computer for the first time, I realized that when I typed something the computer would make the symbols I wanted in the right order, and the right way around, with no effort, and I could easily edit what I had typed to fix letter swaps and typos. It didn’t take any of my mental energy to remember the right shapes or orientation for the letters or any of my patience to make myself draw them. It didn’t sap all of my confidence trying to write something and messing it up over and over. I didn’t realize it at the time, but this was life changing.

From that moment on, I’ve never stopped using and learning about computers.

The Gift of Dyslexia

About 18 years ago–I’m not entirely sure how or why–I read something about dyslexia in an article or on a web site. I had heard about dyslexia before, of course, but had a perception of it as a learning disability – something they talk about in school, but surely not something I had. After all, I was 20 years old, successfully working with computers, reading documentation, writing a thousand-page manual for MySQL, reading and writing emails every day…

I did some quick research, and on May 4, 2002, on a whim, I bought a book from Amazon that would change my entire perception of myself, and completely change the last 18 years of my life since then: The Gift of Dyslexia: Why Some of the Smartest People Can’t Read… and How They Can Learn (now available as a second edition) by Ronald D. Davis.

In The Gift of Dyslexia, Mr. Davis explains some of the workings of the dyslexic mind: the learning “disability” parts of course, but also the distinct advantages that come with it, primarily exceptional spatial reasoning and automatic three-dimensional visualization. In his description in Chapter 1, The Underlying Talent, Mr. Davis says:

The mental function that causes dyslexia is a gift in the truest sense of the word: a natural ability, a talent. It is something special that enhances the individual.

Dyslexics don’t all develop the same gifts, but they do have certain mental functions in common. Here are the basic abilities all dyslexics share:

  1. They can utilize the brain’s ability to alter and create perceptions (the primary ability).
  2. They are highly aware of the environment.
  3. They are more curious than average.
  4. They think mainly in pictures instead of words.
  5. They are highly intuitive and insightful.
  6. They think and perceive multidimensionally (using all the senses).
  7. They can experience thought as reality.
  8. They have vivid imaginations.

These eight basic abilities, if not suppressed, invalidated, or destroyed by parents or the educational process, will result in two characteristics: higher-than-normal intelligence and extraordinary creative abilities. From these the true gift of dyslexia can emerge–the gift of mastery.

I realized quickly that I saw in myself a lot of the advantages of dyslexia, and I immediately recognized the challenges as well. The book goes on to describe several methods to overcome most of the reading challenges associated with dyslexia. It’s not perfect, and I didn’t follow all of its advice, but it set me on a definite path to conquer my own dyslexic reading problems, as well as to understand and embrace the advantages it brought me.

At the time, I was traveling full time for work, flying all over the world, and during that travel I read a lot of basically trash material, as practice. In particular, I read the entire series of John Grisham novels because they were formatted well for me (see below for more on that), they were easy reads, perhaps most importantly they were readily available at every airport book shop so I could pick up a new one after finishing each one. I had to consciously work to apply the methods I learned and make it through these books, but it trained enough of my brain well enough, so that I could read other more difficult material more easily.

Finally, at 20 years old, I learned to read.

What is/was dyslexia like for me?

Before re-learning to read (and even now, if I am tired or too distracted), trying to read a page of text was a challenge: The letters are a jumble. The words are scrambled. I subconsciously read the words in the adjacent lines of text as I am reading. I jump ahead or re-read behind. I read parts of the opposite page. My imagination spins with ideas about what I read. By the time I get to the end of a paragraph, I have no idea what I’ve just read, so I have to read it again. And again. And again.

Aside from the most obvious problems with reading (which I’ve largely overcome), I have many ongoing struggles:

  • My handwriting is atrocious. Unless I am very careful (slow) and methodical, letters will be poorly spaced, mis-ordered, and otherwise pretty unreadable.
  • I can’t take good notes. Since I cannot write by hand quickly enough, or listen and/or think at the same time, handwritten notes are pretty much impossible. I can type to take notes, but that makes the kinds of quick annotations and illustrations that good note-takers usually do very hard.
  • My memory is poor. This is not because of an actual lack of memory, per se, but rather the mechanism by which I form memories. It is more physical and spatial than most. If you just tell me something, it’s gone instantly. I cannot remember singular facts without context. That includes dates, names, amounts, addresses… pretty much anything.
  • I have no sense of order. I will mix up anything that can be flipped or is ambiguous, such as left/right, north/south, east/west, function parameters in programming… the arguments to ln. It doesn’t matter how recently I’ve been told or how recently I’ve used that information.
  • I have no sense of direction. My wife will attest that no matter how many times I’ve been somewhere, or how easy it is to get there, I will get lost. This is mostly because of the previous point about my sense of order.

In re-learning to read, I realized that there are several important factors that go into reading successfully. For me, these are the most important things to understand:

  1. I must always carefully choose the physical layout of the material. The choice of font (and size), and the way a book is typeset, including the size of the margins are all important. Using an e-Reader such as Amazon Kindle helps enormously with this, as for most content I am able to choose the layout features myself. For physical books, I can glance at a few pages and quickly tell if I’ll be able to read it or not. As for me:
    • I prefer simple sans serif fonts without much decoration and with clear letter shapes.
    • I tend towards larger font sizes, as it minimizes distraction from adjacent letters/lines. Tiny text on wide pages is the worst.
    • Perhaps most importantly: Any longer text must be full justified. I find the ragged edges on the right side of a page of left justified text to be so distracting that my reading speed is less than half and I will struggle to get through anything substantial. I realize some people hate full justify, and I’m sorry.
  2. I have to evaluate the writing style of the author. This is a bit harder to describe, and varies a lot by the subject of the material. In general though, for me:
    • I avoid unnecessarily flowery writing styles. Beautiful descriptions of scenes that don’t directly apply to what is happening distract me greatly and I will get lost.
    • A well laid out logical explanation from top-down is usually best. If the author gets mired in the low-level details too early or too often, I will get lost.
    • Illustrations, especially high level or architectural ones help me “set the scene” so that my brain isn’t spending time creating potentially wrong visualizations as I read.
    • Starting with a clear overview or background of what I’m about to read, with definitions, helps a lot.
    • Keeping each paragraph reasonably-sized and on topic helps. Many really short paragraphs (like one sentence) back to back are hard for me to read. Really long paragraphs are impossible for me to read – I get lost in the sea of words.
  3. I always “read aloud” in my mind. For me there is no difference really between reading aloud and reading to myself, except for vocalizing what I am reading. I have the same internal monologue either way, and for me, it’s the only way I can read. (I know this differs with different dyslexics.) This also means that my reading speed is approximately the same (slow) either way.
  4. I use my “mind’s eye” to read. In The Gift of Dyslexia, the author describes fixing in place your “mind’s eye” (the point from which you visualize things) and not letting it wander. This is true for me, and I have to consciously choose to do this while reading text, rather than allowing my mind (and thus my eyes) to wander around the page as it normally would. Imagine my reading as like following the “ball” in karaoke. This is the part that fails first when I am too tired while trying to read.
  5. It’s critical for me to avoid distractions and noise. Until reading The Gift of Dyslexia I really didn’t understand how much simple distractions actually affected me, but they do. I frequently use noise-canceling headphones even without any music playing, just to eliminate the normal house or office noise.

When writing (typing, of course): All of the above applies, but I also have to re-read my writing many times, at least dozens. That’s why it may seem polished to you, the reader. I can’t always write well immediately, but after reading and revising so many times, it probably reads well.

When reviewing someone else’s writing: I will usually take a “style” pass to fix up the spacing, style, typos, font choices, etc., before reviewing. This is not because I’m OCD about style (although I am, as well) but rather that I literally cannot comprehend the content of the writing until I’ve first made it consumable to me. I have to fix those things, or I will trip over them so badly that my reading comprehension of the actual content can be zero. This is a “me” problem, not a you problem.

My dyslexic advantages

I’ve described all of the challenges of being dyslexic, but there are also many advantages.

One of the key things I understood after reading The Gift of Dyslexia and doing subsequent research on dyslexia in general is that the reading challenges associated with dyslexia largely stem from differences in the way the dyslexic person’s brain works. These differences produce many challenges with traditional school especially around reading and writing, but they are fundamentally a beneficial difference for many other aspects of life. So I’ll describe what I see as my “dyslexic advantages”; these are subjective based on my own experience, as I can’t feel or understand how other people’s brains work. For me, though:

  • I visualize in three dimensions. This is the thing that causes so much trouble with reading, because it’s automatic and sometimes uncontrollable, but it’s a very useful skill to have, otherwise. I innately visualize my entire life a lot like a CAD model and mentally rotate objects to see them from other angles. At a glance, I can immediately understand how parts can be joined together, how to assemble or disassemble things, what might be inside a component, etc. This is based partly on imagination, thus it’s not always correct, but it’s largely automatic and effortless.
  • I understand connections. I have an innate sense of the interconnectedness and flow of different systems or components. This applies to computer hardware, electrical systems, plumbing, software, and pretty much any other system. I can sense both how things work and how they or their connections or dependencies can fail. (This does not always extend to making small engines run, though.)
  • I sense correlations. If you’ve worked with me digging through graphs trying to find the source of some bad database traffic, you’ve probably sensed this. I often can’t explain it, but I have an (sometimes almost supernatural) ability to look at a handful of graphs and mentally sort through the noise and figure out causes vs. effects vs. bystanders.

These dyslexic advantages have proven very useful in my professional career working as a computer programmer or working on databases in various web or similar companies. They allow me to understand complex software and systems architectures very easily. I have a good idea how to successfully assemble new systems. In my hobbies and spare time they have allowed me to build very complex devices and electronics for personal projects, to help kids build robots, and to learn to fly airplanes.

Why am I sharing this? Why now?

Through my childhood and my young adult life I was both unaware of my challenges (and dyslexia itself), and ashamed/embarrassed of what those meant. In the intervening years as I came to fully understand my dyslexia and embrace it, I have talked to some people about it, but not very many. To be honest, I am still somewhat embarrassed by it.

Because I could never read during the formative years of my young life, I didn’t read any of the usual books that people generally read. I never developed any love of reading for “fun” as opposed to learning by reading. Even now I don’t really read fiction, I read non-fiction about politics, biographies, and technical topics.

I know there are millions of kids struggling in the same way that I did, without any sort of support network for them. I hope that sharing my story helps at least one struggling child, or helps a parent, teacher, or mentor understand what might be happening. Or… maybe you’re another adult reading this, and it triggers a flash of realization for you.

Reconsidering access paths for index ordering… a dangerous optimization… and a fix!

MySQL has had an interesting optimization for years now1, which has popped up from time to time: in certain circumstances, it may choose to use an index that is index-wise less efficient, but provides the resulting rows in order, to avoid a filesort of the result.

What does this typically look like in production? A query that seems simple and easy takes much longer than it should, sometimes. (Perhaps in production, the query gets killed by pt-kill or exceeds the max_execution_time provided.) The query could be very simple indeed:

SELECT ... WHERE `other_id` = 555 ORDER BY `id` ASC LIMIT 1

There’s an index on other_id, and running the query with an appropriate USE INDEX, the query is fast. Even weirder, changing the query to use LIMIT 10 causes it to run lightning-fast! If anything, the LIMIT 1 should be faster… so, what gives?

Looking at the EXPLAIN, you may notice that the LIMIT 1 version is using access type index on the PRIMARY key (in this case id), whereas the LIMIT 10 version is using ref on a secondary key. Access type index means a full-index scan… on the primary key… which is the clustered key… which is a full table scan.

The optimization is hoping that the LIMIT n with a small enough limit will allow execution to be completed early, without scanning many rows, once the LIMIT is satisfied. This hope is often misplaced: there is no guarantee that there will be any matching rows in the first m rows of the table when ordered by the unwisely-chosen index. Hope is not a strategy.

Although the underlying issue had been reported several times already, under various circumstances, since there were so many individual bugs reported, I filed a new bug with a summary of the situation… and a patch: MySQL Bug 97001.

On MySQL Bug 97001, I proposed a solution (and provided a patch, submitted to Oracle under the NDA) introducing a new optimizer_switch flag named reconsider_index_for_order (defaulting to on to duplicate the current behavior). Although this optimization might benefit some queries, it’s too dependent on the actual data in the involved tables, so it’s not a good candidate for a general optimizer feature in my opinion. Maybe the default could eventually be off allowing users to opt into this optimization when they want it but providing compatible default behavior.

1 The underlying optimization actually appears to be have roots in some very old code, most importantly probably one specific commit in 5.1.

Wireless Programming for FTC Robots

Last Updated: September 11, 2017

[An abbreviated version of this concept was presented at the 2017-2018 FTC season kickoff in Reno, Nevada on September 9, 2017. The slides are available.]

What is the problem?

Programming an FTC robot normally requires the user to connect the robot’s Android device (phone) to the computer via USB and press the “Run” [▶] button in Android Studio. This means getting up from the comfy chair, removing the device from the robot, plugging it into the computer, and then reconnecting it to the robot. This is slow and inefficient. This also means repeatedly unplugging and plugging the Micro-B USB connectors, which are fragile and easily broken. What if that wasn’t necessary?


To get straight to the “how-to” and skip the explanation of how or why this works (and if it’s okay to lose Internet access on the PC while programming or debugging the robot), see the following three most important sections:

  1. Simple: Join the WiFi Direct network from the PC
  2. Add several useful “External Tools” for ADB to Android Studio
  3. Connect wirelessly to program and debug an FTC robot

To avoid losing WiFi internet access on the PC while programming or debugging the robot, see the following additional sections:

  1. Appendix: USB WiFi Models – Acquire a small WiFi adapter.
  2. More elegant: Add a second WiFi adapter to the PC

Otherwise, on to the explanation!

What is ADB?

The Android Debug Bridge (ADB) protocol allows Android Studio to communicate via the adb program with the device, normally attached via USB. ADB allows programs to be stopped and started, files to be copied to or from the device, new APKs to be installed, running processes’ CPU and memory to be monitored, and logs to be accessed (amongst many other actions). When pressing the “Run” [▶] button in Android Studio, adb is used to copy the resulting APK file to the device and install it.

Using ADB over a network

The ADB protocol can be used over a network, so long as it is enabled on the device, via USB, after each time the device has been rebooted. This can be accomplished by running an adb tcpip command to enable TCP/IP (network) access to ADB on the device. This is normally accomplished by running the adb tcpip command (specifying which TCP/IP port to listen on) from the command-line1, while the device is attached via USB:

adb tcpip 5555

Once ADB over TCP/IP has been enabled (in this case on TCP port 5555), any computer can be connected to it over the network by running an adb connect command (and accepting access on the device when prompted):

adb connect

The IP address “” must be replaced with the IP address2 of the Android device being connected to. Once the device is connected over TCP/IP, Android Studio can be used exactly as though it were connected via USB.

A big snag: The FTC Robot Controller uses WiFi Direct

This is where things get somewhat interesting, and specific to FTC robots. The FTC Driver Station and Robot Controller apps use WiFi Direct to communicate with each other. (And normally are disconnected from all other WiFi networks.) This establishes a private WiFi network between the two devices – so, normally, the two devices are not on the same wireless network as the PC where Android Studio is running. There are two solutions to this, but both involve getting the PC onto the same network with the Android devices.

Simple: Join the WiFi Direct network from the PC

It is possible to join the WiFi Direct network created by the FTC Robot Controller app from a PC. The name of the WiFi Direct network is usually known by the team because it’s based on the device name, which is visible in the FTC apps: something like “DIRECT-xy-1234-RC”3. If an attempt is made to join the network from a PC, though, a password is needed to do so. This password can be found using the “Program & Manage” screen in the Robot Controller app’s main menu.

Once the passphrase has been obtained, any PC (or other device) can join its network by selecting the Robot Controller’s network name from the list of WiFi networks on the PC, and using that passphrase for the WiFi password when prompted. Once the PC has successfully joined the WiFi Direct network, ADB can be connected using the Robot Controller’s WiFi Direct IP address (instead of the one obtained from the Android settings menu), which is always

However, this poses a different problem: Now the PC is no longer on the Internet. If while programming, it’s necessary to communicate with team members, use Google to search documentation, or use GitHub to manage code, this becomes very awkward, and would require frequently switching networks, which defeats a lot of the point of this exercise.

More elegant: Add a second WiFi adapter to the PC

A PC is actually quite happy to coexist simultaneously on multiple WiFi (or other) networks, so long as each network has a different IP address scheme. The WiFi Direct network created by the Robot Controller uses 192.168.49.x IP addresses, so as long as the local home/work/school WiFi network uses some other scheme (10.x.y.z or 192.168.0.x are quite typical) then there will be no conflicts.

In order to join the second network, the PC will need an additional WiFi adapter, but fortunately these are quite cheap and very small today: see Appendix: USB WiFi Models for several available models.

After installing the drivers for the new WiFi adapter and plugging it in, simply join the Robot Controller’s WiFi Direct network using the above instructions, but using the new WiFi adapter instead of the computer’s main WiFi adapter. Once connected in this way, the PC should be remain connected to the main WiFi network, and should still have Internet access through that network, while also being able to communicate with the Android device over WiFi Direct.

One possible problem, however, is that the order in which the network devices are connected (or their priority as network adapters) can mean that Internet access may not be available while connected to the Wi-Fi Direct with the second adapter, because Wi-Fi Direct provides an Internet (default) route–even though the device doesn’t itself have Internet access–and the PC may try to use it instead of the other WiFi connection.

This, too, is fixable:

  • On Mac OS X, open the System Preferences and then the Network pane. Click the “gear” icon and select “Set Service Order…” and drag the entries to put “Wi-Fi” above the second Wi-Fi adapter (in the case of the TP-Link adapter, named “802.11n NIC”).
  • On Windows, this problem has not been observed.

Making ADB over TCP/IP easy to use with Android Studio

One additional problem with the above solution is the need to use the adb command – from a command line – to enable TCP/IP and connect to the device. However this is not entirely necessary, either. It can be made to be extremely easy to use in Android Studio!

Add several useful “External Tools” for ADB to Android Studio

Android Studio allows the creation of “External Tools”, which will appear in the main window’s “Tools” menu. These tools can do just about anything, but they can easily be used to run adb commands so that using the command line is no longer required.

In Android Studio, open the main settings panel:

  • On Mac OS, click “Android Studio”, then “Preferences…” (or simply press the hotkey “⌘,”).
  • On Windows, click “File”, then “Settings…”.

In the settings panel:

  1. Expand the “Tools” item
  2. Click “External Tools” to open the External Tools list. The list is normally empty.
  3. For each of the following tools below, click the [+] button, and fill in the provided fields (leaving all others unchanged). Once each tool screen is filled-in, click “OK” to save. (Note: The “Program” field is the same, so the value can be cut and pasted to avoid re-typing.)
  4. Once all tools have been added, click the main settings panel’s “OK” button to save.

“Enable ADB over TCP/IP”

Field Value
Name: Enable ADB over TCP/IP
Program: $ModuleSdkPath$/platform-tools/adb
Parameters: tcpip 5555

“Connect to ADB over WiFi Direct”

Field Value
Name: Connect to ADB over WiFi Direct
Program: $ModuleSdkPath$/platform-tools/adb
Parameters: connect

Bonus: To program the device over a non-WiFi Direct network

The following External Tool is not necessary for programming FTC robots over WiFi Direct, but can be added in order to program any Android device via any other WiFi network. It will prompt for the IP address to connect to.

“Connect to ADB over TCP/IP”

Field Value
Name: Connect to ADB over TCP/IP
Program: $ModuleSdkPath$/platform-tools/adb
Parameters: connect $Prompt$:5555

Connect wirelessly to program and debug an FTC robot

Once the above External Tools are added, connecting to an FTC robot wirelessly to program it and debug it is trivial (after having used USB to program the device at least once4). After each reboot of the Android device (and it doesn’t hurt any other time), follow these steps:

  1. Connect the robot’s Android device to the PC via USB.
  2. Ensure that a file (such as an OpMode) is open and the cursor is in that window5.
  3. Click Tools → External Tools → “Enable ADB over TCP/IP” to enable ADB.
  4. Disconnect the USB cable from the Android device and ensure the computer is connected to the WiFi Direct network with its WiFi adapter.
  5. Ensure the “FTC Robot Controller” app is running on the Android device.
  6. Click Tools → External Tools → “Connect to ADB over WiFi Direct” to connect to ADB.

After the above steps, it may be useful to open the Android Monitor and ensure the connected device is selected in the device drop down (there may be a “[DISCONNECTED]” entry as well, from the previous USB connection; it is not the correct one).

Android Studio should work exactly the same as when it’s connected via USB: the “Run” [▶] button should transfer new APKs to the Android device, and Android Monitor will work even while the robot is running.

A bonus: Use Android Monitor logcat in real time!

Since the device can now remain connected via ADB while the robot is running… that also means that Android Monitor is usable while the robot is running. If the Android logging API (android.util.log) is used to log messages in a program, they will appear in the Android Monitor’s logcat in real time!

Appendix: USB WiFi Models

The author has purchased the below WiFi adapters and tested some of them in the course of writing this document. Reports of good or bad results with additional USB WiFi adapters is welcome either in the comments below or by email.

Nano USB WiFi Adapters

These adapters are small enough not to protrude annoyingly from a laptop computer, and should allow use of a laptop sleeve or case without removal of the device.

TP-Link N150 Wireless Nano USB Adapter (TL-WN725N)

Price: ≈$10 (March 2017, Amazon.com).
Works on Mac OS X and Windows. Have had many signal reception issues on MacBook Pro, possibly caused by antenna not protruding far enough from metal casing. Switched to D-Link DWA-131.

Mini USB WiFi Adapters

These adapters are small (similar in size to a USB thumb drive) but will have to be removed before use of a laptop sleeve or case.

D-Link Wireless N USB Wi-Fi Network Adapter (DWA-131)

Price: ≈$25 (March 2017, Amazon.com).
Works on Mac OS X and Windows. Excellent signal reception and no driver issues on Mac OS X. Appears as a wired-Ethernet adapter with a special app (in the status bar) to configure the WiFi network. Exactly the same chipset as TP-Link N150 (clone of the drivers and app).

NETGEAR AC600 Dual Band Wi-Fi USB Mini Adapter (A6100)

Price: ≈$31 (March 2017, Amazon.com).

Linksys Wireless Mini USB Adapter AC 580 Dual Band (AE6000)

Price: ≈$28 (March 2017, Amazon.com).

Happy wireless programming!

1 “Command Prompt” / “CMD” in Windows or “Terminal” in Mac OS.

2 An Android device’s WiFi IP address can be found by going to the Global Settings → “About phone” → “Status” and checking “IP address” field.

3 The network always starts with “DIRECT” followed by two random letters/numbers, followed by the device name. The device name is required by the FTC game manual rule <RS01> to match this pattern.

4 The FTC Robot Controller app is responsible for creating the WiFi Direct network, so if the app doesn’t exist on the device, it will not be possible to start it to connect over WiFi Direct. Connect the device over USB and program it that way the first time, start the app as instructed, and then wireless programming should work.

5 If the cursor is not in an Android-related file, running the External Tools from this guide may fail with an error about not finding “/platform-tools/adb” – because the $ModuleSdkPath$ macro used in the External Tool definition will not have been filled with the appropriate Android SDK path. To make the External Tool work with any cursor location, just replace the $ModuleSdkPath$ macro with its actual value, which can be found by clicking “Insert macro…” and selecting $ModuleSdkPath$. The downside of this solution is that if the path changes (for instance due to an upgrade), the External Tool entry may cease to work anymore.

Black History Month

[This was originally posted on Facebook, but has been copied here and backdated appropriately.]

This month – February – is Black History Month.

This month is not about me, but I hope that you will all bear with me for a moment and forgive me as I use the word “I” more than I should:

I was born in Tennessee – the American South – and despite many of my peers being people of color and various races, I was raised as a product of the white-centric American education system. That means, basically, that my understanding of black history amounted to little more than “we used to be mean to black people and call them names [whispering: and hang a few], but we stopped doing that a long time ago and made them EQUAL, and now they just like to do drugs and riot a lot about what happened in the past”.

I accepted this completely wrong “definition” of Black history (and present), not knowing any better, for a long time. Not because I thought it was right, but because it didn’t materially affect me. As an utterly privileged white male, I never really thought much about it. I accepted that it was normal to occasionally hear denigrating comments towards people of any color or of non-Christian religions – it’s the South, after all! I accepted that some of my family just “didn’t like black people”, and that was normal, right? I accepted that it was all just good fun, and everybody jokes, and jokes are harmless, right? I accepted that it was normal to hear people joke about “ebonics” or to mock religious practices or clothing.

I personally didn’t like it, and I attempted not to participate or encourage it, but I accepted it, and I admit that I certainly did participate on occasion.

I now accept that I was wrong, and that I can do better.

I contributed – even if primarily passively – to racism, to discrimination, to hurting people, and I refuse to do that or accept it from anyone else any longer.

I ignored or looked away or walked away far too often, and I refuse to ignore or look away or walk away any longer.

I ignored Black History Month, because I am not black. That was wrong, too.

Black History Month is not about or for black people celebrating black history – having a beer and toasting Dr. King, as I perhaps previously imagined – it’s for everyone (and especially everyone that’s not black). It’s about recognizing the impacts that everyone has had on black history, and especially how those impacts have molded and shaped what it means to be black in America. Many of those impacts have been negative and uncomfortable for white people like myself. Many of those impacts have been positive (and unfortunately often still uncomfortable for white people!).

This month is about recognition – both the joyous and the solemn kind. This month is also about, after achieving some recognition, offering unguarded praise and optimism for black innovation and advances, offering condolences for black sacrifice, shedding tears for black repression and suffering, and offering your heart to accepting and embracing Black History.

Black History Month is not about making blacks equal to whites somehow by giving them a month and marking it on everyone’s calendars. It’s about having the fortitude and compassion and sense to both accept the ugly past, and commit to making blacks and Black Future BETTER than your own. After all, by embracing each other, acknowledging and embracing our differences, and pushing each other higher, nobody actually gets left behind – we all rise up together.

You are black. I see that you are black. I love your blackness. I am sorry for everything. I love you. I will fight for you.