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?

How-to

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 1.2.3.4:5555

The IP address “1.2.3.4” 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 192.168.49.1.

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 192.168.49.1:5555

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).
Windows-only.

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

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

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.

Join me… Invest in Humanity, too

In Invest in Humanity 2016 I introduced my project to “invest” an initial $60,000, by supporting groups/organizations all around the country, with a singular goal: to improve humanity. It’s still going strong, in fact we’ve now given about 75% of the budget—almost $47,000—to 118 different organizations. You can read a bit more and see the current list of organizations and causes we’ve supported at InvestInHumanity2016.com.

Will you join me, and Invest in Humanity, too?

I started this project as an experiment, and with the hope that I could inspire at least a few others to follow me, and invest in humanity along with me. It’s going to take a little bit from a lot of us to make a dent in really improving and furthering humanity. So now I’d like to put out a call to do just that: Will you choose to invest in bettering humanity? I’d love to see people join me at both ends of the scale spectrum:

If you can make one small donation to just one organization which helps/benefits people in other areas or circumstances, every bit helps.

If, however, you have the resources to do something bigger and grander… perhaps even similar to what I’ve been doing, I’d be happy to talk to you about how it’s worked and help you along, or even do much of the work for you. Feel free to reach out to me any time at jeremy@investinhumanity2016.com.

With all of your help, we can and we will build a society that is collectively better than any of us could be individually.