<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>jflanagan again</title>
    <description>Longer-form thoughts from Joshua Flanagan, a software developer in Austin, TX
</description>
    <link>http://www.joshuaflanagan.com/blog/blog/</link>
    <atom:link href="http://www.joshuaflanagan.com/blog/blog/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 19 Jul 2020 12:53:37 -0500</pubDate>
    <lastBuildDate>Sun, 19 Jul 2020 12:53:37 -0500</lastBuildDate>
    <generator>Jekyll v3.8.7</generator>
    
      <item>
        <title>Build your own head tracker</title>
        <description>&lt;p&gt;My son has been playing a lot of the &lt;a href=&quot;https://www.digitalcombatsimulator.com&quot;&gt;DCS World&lt;/a&gt;
flight simulator lately, and started talking about building a head tracker. I
didn’t even know this was a thing, outside of expensive Virtual Reality gear.
A head tracker is a relatively low cost device that allows you to control your
view in a game (look around the cockpit) just by moving your head - so you can
keep your hands focused on steering and throttle, etc. He had read about building
an infrared based tracker for $10 - but the parts needed didn’t seem convenient
(PlayStation 3 camera and a floppy disk? - google it, you may like that solution better).
Since I have &lt;a href=&quot;/blog/2015/11/07/build-your-own-single-function-keyboard.html&quot;&gt;experience with programming a Teensy&lt;/a&gt;,
I knew it was possible to create a relatively cheap device that could simulate a
game controller. After searching for “head tracker teensy” I came across this
&lt;a href=&quot;http://crispycircuits.blogspot.com/2018/06/inertial-head-tracker.html&quot;&gt;Inertial Head Tracker post&lt;/a&gt;
which had the exact same idea, and had already done most of the hard work for me.&lt;/p&gt;

&lt;p&gt;However, some of the details on that post were a little unclear, and I had a lot
of trouble with the source code on that page - I have a feeling it was corrupted
somehow in the publishing process because some of it just doesn’t make sense and
will not compile. I’m going to add my interpretation, and code, for what needs to be
done, but defer all credit for this idea to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmarzano&lt;/code&gt;, the author of that post.&lt;/p&gt;

&lt;h2 id=&quot;parts&quot;&gt;Parts&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.pjrc.com/store/teensy32.html&quot;&gt;Teensy 3.2 w/pins&lt;/a&gt; - you &lt;em&gt;might&lt;/em&gt; be
able to save some money by using the Teensy-LC - I have not tried it. Newer
versions of the Teensy should also work. I bought the &lt;a href=&quot;https://www.pjrc.com/store/teensy32_pins.html&quot;&gt;version with pins&lt;/a&gt; to save
me some soldering work.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.pjrc.com/store/prop_shield.html&quot;&gt;Teensy Prop Shield w/Motion Sensors&lt;/a&gt; -
it should be obvious that you cannot use the low cost Prop Shield, since the motion
sensors are the part we need.&lt;/li&gt;
  &lt;li&gt;A long micro-USB cable. Long enough to allow freedom to connect the device on your
head to your computer. I went with one of these &lt;a href=&quot;https://smile.amazon.com/gp/product/B07JBN6C5C&quot;&gt;10ft cables&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://smile.amazon.com/2-54mm-Breakaway-Female-Connector-Arduino/dp/B01MQ48T2V/&quot;&gt;Some header pins&lt;/a&gt; to make it easier to mount the Prop Shield on the Teensy.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.pjrc.com/teensy/td_download.html&quot;&gt;Teensyduino IDE&lt;/a&gt; - used to compile and publish programs to your Teensy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;instructions&quot;&gt;Instructions&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;These instructions were mostly lifted from the original post - the original
author deserves the credit, I just added some clarification on parts that confused me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;1) You need to connect the Prop Shield to the Teensy. The easiest way (assuming
you have a soldering iron, and know how to use it), is to attach some female
header connectors to the Prop Shield. You only need to connect the long sides.
Connect the male header connectors to the bottom of the Teensy (or buy the version with pins).
If you do not want to use header connectors, look at the diagram and table in the
“Technical Details” section of &lt;a href=&quot;https://www.pjrc.com/store/prop_shield.html&quot;&gt;the Prop Shield page&lt;/a&gt;
to identify the pins that need to be connected to make the sensors work (follow
the Used By column in the table). The header connectors make it easier to remove
the Teensy from the Prop sheild, but if you want a permanant connection, you can
probable get a lower profile by not using headers.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/teensy_and_prop_shield.jpg&quot; alt=&quot;Teensy and Prop Shield with header connectors&quot; /&gt;&lt;/p&gt;

&lt;p&gt;2) Mount the Teensy+Prop to a hat or headset. I &lt;a href=&quot;https://www.thingiverse.com/thing:4546801&quot;&gt;3D printed a small box to hold it&lt;/a&gt;,
and used some heavy duty velcro to attach it (stick the soft side on the headset).
It is important to mount it before calibrating it, since the calibration is
impacted by other things around it.&lt;/p&gt;

&lt;p&gt;3) Install and configure the Teensyduino/Arduino software. Open Teensy/Arduino -
the first thing you should do is go to the Tools menu and choose your Board (Teensy 3.2 for me).
Now when you open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File | Examples&lt;/code&gt; menu, there should be a Teensy 3.2 section that includes NXPMotionSense.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;If you don’t see the NXPMotionSense examples, you can download them from
the &lt;a href=&quot;https://github.com/PaulStoffregen/NXPMotionSense&quot;&gt;NXPMotionSense github page&lt;/a&gt;,
click on Code, and Download Zip. Extract the zip to a directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CalibrateSensors&lt;/code&gt; example sketch from the NXPMotionSense group. (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File | Examples | NXPMotionSense | CalibrateSensors&lt;/code&gt;).
Or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File | Open&lt;/code&gt; and find the sketch in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;examples&lt;/code&gt; directory of the extracted zip.&lt;/p&gt;

&lt;p&gt;4) Click the Verify button (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sketch | Verify&lt;/code&gt; menu)
to make sure it works. If it compiles, connect the Teensy to your computer with
the USB cable, and click the Upload button. This should start running the CalibrateSensors
program on the Teensy. You can open the Serial Monitor from the Tools menu to
see the calibration data output. You should notice different numbers change, depending
on how you position the Teensy. After confirming it is working, close the Serial Monitor
 so that it does not interfere with MotionCal in the next step.&lt;/p&gt;

&lt;p&gt;5) Download and run the &lt;a href=&quot;https://www.pjrc.com/store/prop_shield.html&quot;&gt;MotionCal application from the Prop Shield page&lt;/a&gt;.
Select the COM port for the Teensy. Move the Teensy around through all axis of rotation - you
should see the red dots start to form a sphere. You need to move it around until
all of the numbers are below 5%. Once you reach that goal, the “Send Cal” button
will be enabled. Press that button to write the calibration data to the Teensy’s EEPROM.&lt;/p&gt;

&lt;p&gt;6) Open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MahonyIMU&lt;/code&gt; example sketch from the NXPMotionSense group (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File|Examples|NXPMotionSense|MahonyIMU&lt;/code&gt;)
In the Teensy IDE, change the USB Type from Serial to “Flight Sim Controls + Joystick”.
Click the Verify button. If it works - great! But you will likely get a fatal error stating that it cannot find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MahonyAHRS.h&lt;/code&gt;.
You need to install the MahonyAHRS library. As of this writing, the version (1.1) available in the Arduine Library Manager
does &lt;em&gt;not&lt;/em&gt; work. You need to install the latest unreleased copy from the source. Go to &lt;a href=&quot;https://github.com/PaulStoffregen/MahonyAHRS&quot;&gt;https://github.com/PaulStoffregen/MahonyAHRS&lt;/a&gt;,
click Code, Download Zip. Extract the zip to your Arduino libraries directory (which is likely &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Arduino/libraries&lt;/code&gt; in your user &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Documents&lt;/code&gt; directory).
With the library installed, you should be able to Verify the sketch successfully. (I did see some &lt;em&gt;warnings&lt;/em&gt; but they can be ignored).
Once it is successfully verified, upload it to the Teensy.&lt;/p&gt;

&lt;p&gt;7) &lt;em&gt;from the original post&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Put your headset on and open the Arduino Serial Monitor. You will see the current values of heading, pitch, and roll in order.
The values shown will vary with each setup depending on the mounting orientation
of your Teensy and the direction your computer desk is facing. Note the heading
value when you are looking straight ahead after about 1 minute has elapsed.
The 1 minute wait is necessary for the algorithm to reduce the error with the magnetometer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;8) Create a new Sketch (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File | New&lt;/code&gt;), paste in the code from below, and save it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HeadtrackJoystick&lt;/code&gt;.
Change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;headingcenter=328&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void setup()&lt;/code&gt; function and set it to the
heading value you observed when facing your computer (from the previous step). This determines
the center position of the joystick.&lt;/p&gt;

&lt;p&gt;9) &lt;em&gt;from the original post&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Save the updated code to a safe place and flash the Teensy. It is now functioning as a USB joystick. You can view the output in the Arduino Serial Monitor for debugging if necessary, or launch the Windows “Set up USB Game Controllers” application to see windows receiving the data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;10) &lt;em&gt;from the original post&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Launch OpenTrack and adjust the input to use the Teensy. Depending on your luck, you may need to invert axes to match your movement. You can also adjust sensitivity, smoothing, and define curves in OpenTrack. For the output settings, set the interface option as “Use TrackIR, hide FreeTrack” to be compatible with most TrackIR compatible applications. I highly recommend setting a bind key for “Center” under “Options” to have the software adjust the resting center. This is to account for small differences in your positioning as every time you use the head tracker, you will have a slightly different resting position.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;
&lt;p&gt;Instead of using the code from the original post, use mine below (or, if gets mangled
like it did on the original post, you can always &lt;a href=&quot;https://github.com/joshuaflanagan/head_tracker/blob/master/HeadtrackJoystick.ino&quot;&gt;get the latest version from my Github&lt;/a&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// HeadtrackJoystick, based on:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Inertial Monitoring Unit (IMU) using Mahony filter.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// https://github.com/PaulStoffregen/NXPMotionSense/blob/master/examples/MahonyIMU/MahonyIMU.ino&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// and inspired by the code example on http://crispycircuits.blogspot.com/2018/06/inertial-head-tracker.html&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;NXPMotionSense.h&amp;gt;
#include &amp;lt;MahonyAHRS.h&amp;gt;
#include &amp;lt;Wire.h&amp;gt;
#include &amp;lt;EEPROM.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;NXPMotionSense&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Mahony&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;joyheading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;joypitch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;joyroll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headingcenter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headingoffset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;imu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 100 measurements per second&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;//TODO: make this settable by pressing a button&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;headingcenter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;328&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;headingoffset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headingcenter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;az&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;roll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pitch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;available&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Read the motion sensors&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;imu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readMotionSensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;az&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Update the Mahony filter&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;az&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// print the heading, pitch and roll&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;heading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getYaw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//  0..360&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pitch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getPitch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//  -90..90&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;roll&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getRoll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// -180..180&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Orientation: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pitch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;roll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// The heading is a number retrieved from the sensor, which indicates a&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// compass direction (degrees) using a number from 0-359.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// We want to use that number from a sensor to indicate which way our&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// &quot;joystick&quot; is pointing. If you are looking straight at your computer,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// the joystick should be centered, and you can look up to 180 degrees in&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// each direction.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Since not everyone will be looking due South at the their computer, we&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// need to map their actual heading (specified by headingcenter) so that it&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// can be used as the neutral position of the joystick. The adjustedheading&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// is the actual heading, mapped to a new 360 degree range.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headingoffset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;360&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;360&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;360&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// The heading value from the sensor has 360 values. The Teensy joystick&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// driver expects a value from 0-1023, with 512 indicating the center. Map&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// the sensor value as a fraction of the joystick range.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;joyheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adjustedheading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;360&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1023&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// The pitch value from the sensor has 180 values. Map the sensor value as&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// a fraction of the joystick range.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;joypitch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pitch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1023&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// The roll value from the center has 360 values. Map the sensor value as&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// a fraction of the joystick range.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;joyroll&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;roll&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;360&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1023&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Send the sensor data as joystick input to the computer&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Joystick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joyheading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Joystick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joypitch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Joystick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joyroll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Joyvalue: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joyheading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joypitch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joyroll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sat, 18 Jul 2020 18:40:31 -0500</pubDate>
        <link>http://www.joshuaflanagan.com/blog/blog/2020/07/18/build-your-own-head-tracker.html</link>
        <guid isPermaLink="true">http://www.joshuaflanagan.com/blog/blog/2020/07/18/build-your-own-head-tracker.html</guid>
        
        
      </item>
    
      <item>
        <title>Infinity ErgoDox Build Guide Companion</title>
        <description>&lt;p&gt;This article is intended to be a companion to the official &lt;a href=&quot;http://input.club/devices/infinity-ergodox/infinity-ergodox-build-guide&quot;&gt;Infinity ErgoDox build guide&lt;/a&gt;
maintained by Input Club.  As a first-time keyboard builder, there were a number
of steps that were not very clear to me. My hope is that this will help other
novice builders build their keyboard with more confidence.
It is &lt;em&gt;not&lt;/em&gt; intended to replace the build guide, and it skips some steps that do not
require any further clarification.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;NOTE: You should be aware that there are &lt;em&gt;two&lt;/em&gt; different build guides for the Infinity ErgoDox
on the input.club site. Which one you get depends on the navigation steps you take.
The one that appears to be the most up-to-date is the one I linked to above - you
reach it by choosing “Infinity ErgoDox Kit” from the “Devices” menu on the input.club
website, and then following the link to the Build Guide (it will have “devices” in the url).
However, if you choose “FAQs” from the “Forums” top menu, and follow the “Build Guide: Infinity ErgoDox”
link, you will see an older version of the build guide (it will have “knowledgebase” in the url).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;pre-step-1-warning&quot;&gt;Pre-step 1 warning:&lt;/h3&gt;
&lt;p&gt;The latest version of the build guide (as of this writing) contains a warning before
the first step about a potential weakness of the USB connectors.
It suggests adding some solder to the pins, but those connections looked &lt;em&gt;way&lt;/em&gt; too
small for my soldering experience level and/or tools. Instead, I opted to reinforce
all of the connectors with &lt;a href=&quot;http://www.homedepot.com/p/Loctite-0-85-fl-oz-Metal-and-Concrete-Epoxy-Syringe-1405605/100371817&quot;&gt;non-conductive metal epoxy&lt;/a&gt;,
as suggested in the forums. The forums weren’t very specific on how much, so I
&lt;em&gt;covered&lt;/em&gt; the ports as much as I could. I spent too much money and waited too long
to have the keyboard break on me now. But a bit of warning - it was only after I
assembled the full keyboard that I realized the case is transparent, so my
&lt;a href=&quot;/blog/assets/iced_usb_epoxy.jpg&quot;&gt;sloppy globs of epoxy on the USB-A connector&lt;/a&gt;
are visible. I can live with that, as long
as it all stays together, but you may want to be more careful to stay to the sides
and back of those connectors (the micro-B connectors are covered after assembly,
so it is okay to cover them - just be aware if you make the covering &lt;em&gt;too&lt;/em&gt; thick,
it may interfere with attaching the PCB to the switch plate).&lt;/p&gt;

&lt;h3 id=&quot;step-1&quot;&gt;Step 1:&lt;/h3&gt;
&lt;p&gt;Verify your components. I didn’t really know what I was looking for at the
time, but after I assembled my keyboard I had one key that didn’t work, which I
traced to a faulty diode. It was crooked, and the casing was slightly peeled back.
I contacted Massdrop support as they suggest, and they sent me a few spare diodes
right away. This is just a reminder that they are there to help if needed.&lt;/p&gt;

&lt;h3 id=&quot;step-3&quot;&gt;Step 3:&lt;/h3&gt;
&lt;p&gt;This step tells you to verify that you have all of the case layers. It
lists them out, but unfortunately, the names like “Top Plate #1” didn’t mean
much to me. I could count the layers and verify there were two of each shape. But
throughout the build I was worried that I would mess up the order of
the layers. I’m not sure if you &lt;em&gt;can&lt;/em&gt; put them together improperly, but just in
case, I’ve taken some photos to help you identify them:&lt;/p&gt;

&lt;p&gt;The top plates go above the switch plate. You can differentiate the top plates
from the bottom spacer plates because the top plates are a closed shape that goes around the
entire perimeter of the keyboard. The bottom spacer plates are &lt;em&gt;open&lt;/em&gt;, in that there
is a break in the perimeter (where the USB connectors go). Click the plate names
to see a photo.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/assets/iced_top_plate_2.jpg&quot;&gt;Top Plate #2&lt;/a&gt;: the thinner of the two closed shapes. The acrylic covers the area
where the LCD will be (top-left on left-hand keyboard).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/assets/iced_top_plate_1.jpg&quot;&gt;Top Plate #1&lt;/a&gt;: the thicker of the two closed shapes. There is an opening where
the LCD will be.&lt;/li&gt;
  &lt;li&gt;Switch Plate: this is more obvious, as the only aluminum piece.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/assets/iced_spacer_plate_1.jpg&quot;&gt;Spacer Plate #1&lt;/a&gt;: the thinner of the two open shapes. It has a larger notch
for the LCD.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/assets/iced_spacer_plate_2.jpg&quot;&gt;Spacer Plate #2&lt;/a&gt;: the thicker of the two open shapes. It has a small notch
for the LCD.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/assets/iced_bottom_plate.jpg&quot;&gt;Bottom Plate&lt;/a&gt;: also obvious, as it is the only acrylic piece that doesn’t
have a hole it the middle. It covers the entire bottom of the keyboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;step-4&quot;&gt;Step 4:&lt;/h3&gt;
&lt;p&gt;Remove the backing paper. I &lt;em&gt;wish&lt;/em&gt; I had a good tip for this step. It
took me much longer than I care to admit. You can probably do it a lot faster
if you are more aggressive.&lt;/p&gt;

&lt;h3 id=&quot;steps-5-7&quot;&gt;Steps 5-7:&lt;/h3&gt;
&lt;p&gt;Definitely the most confusing steps in the guide. I think it assumes
a lot more familiarity with stabilizers. They are the white plastic pieces that
help keep the larger keycaps from wobbling on top of the switch. Hopefully a
photo of the finished product will help you better visualize each step.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/iced_stabilizers.jpg&quot; alt=&quot;side view of stabilized keys&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The other confusing part of this step is that it refers to the “stabilized switches”,
and even shows a switch mounted on the switch plate, and yet none of the previous
steps mentioned anything about mounting a switch! It wasn’t clear to me if I
should be attaching a switch so early in the process. It turns out you can - &lt;em&gt;but&lt;/em&gt;
you’ll want to make sure you mount it in the correct direction. When the switch
is face up (you can press in the mechanical button on the top), there are two
clips on the north and south edges (I’m referring to a Cherry MX switch, I am
not sure how much other brands differ).
&lt;a href=&quot;/blog/assets/iced_cherry_switch.jpg&quot;&gt;On the north side, you can see the word “Cherry” in the plastic&lt;/a&gt;.
This is the same end that has the two pins on the bottom
of the switch. When attaching the thumb keys that have the stabilizers, it is very
important that you position the end of the switch with the pins so that they are closer
to the inner/main body of the plate. The other end is toward the outer/thumb area
edge of the plate.&lt;/p&gt;

&lt;h3 id=&quot;step-7&quot;&gt;Step 7:&lt;/h3&gt;
&lt;p&gt;This is the most vague step. At this point you should have two long white
plastic stabilizer inserted into the switch plate (for each stabilized key), and
a switch mounted in between them (pins closer to the main portion). Attach the
wire to the two stabilizers as shown in the build guide, with the wire going
along the edge closer to the outside of the keyboard.
Now locate the keycaps that will attach to the stabilized switches. If you bought your
keycaps from Massdrop, these will be the largest size keycaps. They have three
holes on the bottom. The middle hole will attach to the switch. For the other holes,
you need to insert the small white plastic pieces that came with the stabilizers.
When “face up” (the part that will insert into keycap on top), there is a longer
portion that extends from one end. You want this end facing toward the inner
body of the keyboard. Figure out which way you want to mount your keycaps (mine
have one side that is vertical, and the other side is slanted - I chose to mount
mine with the vertical side facing the inner part of the keyboard), and then
attach the two white inserts in the outer holes on the keycap so that the long
edge of the inserts face the correct direction.
Now press on the middle of the wire so that the ends angle up slightly. Connect
the keycap with the inserts to one edge of the wire, by pushing the wire through
the hole on the insert. Then try and angle the keycap down so that you can put
the other end of the wire into the hole on the other insert. This can be tricky.
I used a tiny screwdriver to push out against the side of the wire to make it
open wider when attaching the second insert. Once the wire is in both ends, try
and position the “button” on the switch so that it is lined up with the middle
hole on the keycap, and then push down firmly. Press the key a few times
to make sure it is connected, and slides up and down easily. The stabilizer
might “catch”, preventing the key from rising back to its proper height. This
seems to be a common problem. I fixed mine by just pressing it a bunch and it
worked itself out. Other people suggest &lt;a href=&quot;http://www.wasdkeyboards.com/index.php/super-lube-silicone-lubricating-grease-with-ptfe.html&quot;&gt;lubricating&lt;/a&gt;
the stabilizers. &lt;a href=&quot;https://youtu.be/oWgrnQGBBn4?t=4m2s&quot;&gt;This video&lt;/a&gt;
shows is a good demonstration of attaching the keycap to the stabilizers and switch,
and also shows how to lubricate them, if needed.&lt;/p&gt;

&lt;h3 id=&quot;step-8&quot;&gt;Step 8:&lt;/h3&gt;
&lt;p&gt;Again, take care that you orient the switches correctly. It helps to look
at the PCB to see the holes through which the switch pins will go. The switches will attach to
the side of the PCB with the LCD face up. In most places, this means the pins
of the switch will be on the &lt;em&gt;south&lt;/em&gt; edge (so the Cherry logo is upside-down).
There are a few places where the switch is oriented side-ways - in those cases,
the pins should be oriented so that they are on the edge closer to the inner
part of the keyboard.&lt;/p&gt;

&lt;h3 id=&quot;step-9&quot;&gt;Step 9:&lt;/h3&gt;
&lt;p&gt;If you have trouble attaching the switch plate to the PCB, you probably
have some of the switches in the wrong direction, so the pins aren’t lined up
with any holes (I had this problem my first time). Remove the misplaced switch
(squeeze the 2 clips on the top and bottom) and re-position.&lt;/p&gt;

&lt;h3 id=&quot;step-10&quot;&gt;Step 10:&lt;/h3&gt;
&lt;p&gt;After soldering on the stabilized switches, I think its a good idea to
verify things are working properly. Plug the PCB back into computer (as in Step #2)
and press the keys. Hopefully, you should see the proper response from the computer.
See &lt;a href=&quot;http://input.club/configurator-ergodox&quot;&gt;the configurator&lt;/a&gt; to get an idea of expected functions of each key in the
default layout. The stabilized keys should be (left hand) Backspace and Delete, and
(right hand) Space and Return. I did this verification occassionally throughout the
entire process of soldering on the rest of the switches (unplugging from the computer
during the soldering steps).&lt;/p&gt;

&lt;h3 id=&quot;step-13&quot;&gt;Step 13:&lt;/h3&gt;
&lt;p&gt;This is a good point to flash your keyboard with the latest firmware. The
layout that comes pre-installed does &lt;em&gt;not&lt;/em&gt; include a function for entering Flash
mode, which means you need to disassemble the keyboard (so that you can press
the flash button on the bottom of the PCB) any time you want to upgrade
the firmware/change the layout. The latest firmware maps a key to Flash mode, so
you do not have to press the button on the bottom.&lt;/p&gt;

&lt;h3 id=&quot;step-16&quot;&gt;Step 16:&lt;/h3&gt;
&lt;p&gt;Installing the (optional) LEDs is mostly straightforward, but there are a couple
tips that will make things go more smoothly. After you have pushed the LED through
the switch and PCB (correctly oriented so the long wire goes through the square
hole), make sure it is in as far as it will go before you solder it. I held a
finger against the LED on the other side of the board while I soldered it to make
sure it didn’t slip out at all. If the LED sits just a small amount above the
switch, it may interfere with the keycap when you press the key.
After the two wires are soldered in, you’ll need to trim them as close to the
solder joint as possible. If the wires extend too long, they will make it
difficult to attach the backplate and get a tight seal, and put extra pressure
on the solder joints. However, be careful when clipping the wires - make sure
you dont clip any adjacent components on the board.&lt;/p&gt;

&lt;h3 id=&quot;step-18a&quot;&gt;Step 18a:&lt;/h3&gt;
&lt;p&gt;I already mentioned that Step 13 is a better time to flash your
keyboard - not sure why they suggest waiting until you have it stacked on all
of the acrylic pieces. However, this &lt;em&gt;is&lt;/em&gt; a good time to consider &lt;a href=&quot;http://input.club/forums/topic/reset-hole/page/2/#post-1508&quot;&gt;drilling a
hole in the backplate&lt;/a&gt;
to allow access to the flash button on the PCB. Since the backplate is attached
to the PCB (but not screwed it), you can mark the location for the drill hole
above the flash button with a small marker. Then you’ll remove the backplate
and do the drilling.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;WARNING: Massdrop does not recommend the drilling step, as you may seriously
crack or damage the acrylic. It worked well for me and others, but there is
definitely risk involved.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;step-20&quot;&gt;Step 20:&lt;/h3&gt;
&lt;p&gt;Installing DCS caps is a bit tedious. The first step is to sort all
of the keycaps into the four different slopes (1-4). This can be a little
tricky, as they can look very similar. If you look at an individual keycap from
above, you’ll notice that one of the four sides is not sloped. Organize all of
your keys so that the side without the slope is on the left. If you line up keys
against each other, with the unsloped end aways on the left, you will be able to
tell if they are the same or not. If they are the same, place the match in line
behind the first one. If the are not the same, place it to the side to start a new line.
You should end up with four different lines. This photo should help you identify
the keyboard &lt;em&gt;row number&lt;/em&gt; for each line (in increasing order from left to right):
&lt;img src=&quot;/blog/assets/iced_dcs_keycaps.jpg&quot; alt=&quot;DCS keycaps 1-4&quot; /&gt;
Row 1 is the tallest and row 4 has the steepest top slope.
Once you know the row number, you can use &lt;a href=&quot;http://www.keyboard-layout-editor.com/#/layouts/8853e7a752ee3e156e968ffb3b1389d1&quot;&gt;this illustration as a guide to where each type of keycap belongs&lt;/a&gt;.
When you attach the keycaps, the non-sloped side should face either the top (north)
end of the keyboard, or the &lt;em&gt;inner&lt;/em&gt; part of the keyboard (if it is a sideways key).&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I plan to post a follow-up article with instructions on customizing your keyboard
layout. Until then, check out the &lt;a href=&quot;http://input.club/configurator-ergodox&quot;&gt;online configurator&lt;/a&gt;
and the &lt;a href=&quot;https://github.com/kiibohd/controller/wiki/How-To-Load-Layouts-to-Keyboard&quot;&gt;controller code wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should also check out the &lt;a href=&quot;http://www.burritoware.me/proj/infinity-ergodox/&quot;&gt;burritoware commentary&lt;/a&gt;,
as I found it helpful during my first build.&lt;/p&gt;

&lt;p&gt;If any of the steps above need correction or clarification, &lt;a href=&quot;http://input.club/forums/topic/build-guide-companion&quot;&gt;please mention it on the input.club forums&lt;/a&gt;,
or &lt;a href=&quot;https://twitter.com/jflanagan&quot;&gt;contact me on twitter&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;
&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-sa/4.0/&quot;&gt;
&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width:0&quot; src=&quot;https://i.creativecommons.org/l/by-sa/4.0/88x31.png&quot; /&gt;
&lt;/a&gt;
&lt;br /&gt;
&lt;span xmlns:dct=&quot;http://purl.org/dc/terms/&quot; property=&quot;dct:title&quot;&gt;Infinity Ergodox Build Guide Companion&lt;/span&gt; by &lt;a xmlns:cc=&quot;http://creativecommons.org/ns#&quot; href=&quot;http://www.joshuaflanagan.com/blog/2015/11/21/infinity-ergodox-build-guide-companion.html&quot; property=&quot;cc:attributionName&quot; rel=&quot;cc:attributionURL&quot;&gt;Joshua Flanagan&lt;/a&gt; is licensed under a &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-sa/4.0/&quot;&gt;Creative Commons Attribution-ShareAlike 4.0 International License&lt;/a&gt;.
Explicit permission is granted to the Infinity ErgoDox Build Guide hosted at &lt;a href=&quot;http://input.club/devices/infinity-ergodox/infinity-ergodox-build-guide&quot;&gt;http://input.club/devices/infinity-ergodox/infinity-ergodox-build-guide&lt;/a&gt; to incorporate any portion of this work without attribution.&lt;/p&gt;
</description>
        <pubDate>Sat, 21 Nov 2015 18:49:27 -0600</pubDate>
        <link>http://www.joshuaflanagan.com/blog/blog/2015/11/21/infinity-ergodox-build-guide-companion.html</link>
        <guid isPermaLink="true">http://www.joshuaflanagan.com/blog/blog/2015/11/21/infinity-ergodox-build-guide-companion.html</guid>
        
        
      </item>
    
      <item>
        <title>Build Your Own Single Function Keyboard</title>
        <description>&lt;p&gt;I mentioned in &lt;a href=&quot;/blog/2015/11/02/infinity-ergodox.html&quot;&gt;my last post&lt;/a&gt; that it took
months between the time I ordered my Infinity Ergodox keyboard and the time it arrived.
In the meantime, I &lt;a href=&quot;http://people.eecs.ku.edu/~tlindsey/ErgoDox_FAQ.html&quot;&gt;started reading up on it&lt;/a&gt;,
and learned that the firmware could also run on a &lt;a href=&quot;https://www.pjrc.com/teensy/index.html&quot;&gt;Teensy&lt;/a&gt;.
I didn’t know what a Teensy was, so started researching. Its a low-cost
development board that is (mostly) Arduino compatible, and excels at building
USB input devices. Using the &lt;a href=&quot;https://www.pjrc.com/teensy/teensyduino.html&quot;&gt;Teensyduino software&lt;/a&gt;,
you can easily configure the type of device it will appear as to your computer (USB mouse, USB keyboard, etc).&lt;/p&gt;

&lt;p&gt;I decided I’d try my hand at building my &lt;em&gt;own&lt;/em&gt; keyboard. But this one would be
very special. It would have one key, with one function: approve GitHub pull requests!
At ShippingEasy, all of our code goes through a Pull Request. Before you can
merge the Pull Request, someone else has to approve it. By convention, we indicate
approval with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:+1:&lt;/code&gt; emoji (also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:thumbsup:&lt;/code&gt;). So I wanted a big, red button
that I could slap to approve a pull request.&lt;/p&gt;

&lt;p&gt;Turns out, its pretty easy to do. My search for a big red button led me to the
&lt;a href=&quot;http://www.staples.com/Staples-Easy-Button-/product_606396&quot;&gt;Staples Easy Button&lt;/a&gt;,
which has a good reputation for these types of crafty projects. The button is
very sturdy, so it can handle your emphatic code review approvals.
&lt;img src=&quot;/blog/assets/pr_button_complete.jpg&quot; alt=&quot;finished button&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The electronics part of the project was very straightforward. I disassembled
the Easy button (&lt;a href=&quot;http://www.instructables.com/id/Z-Wave-Easy-Button/step2/Disassemble-The-Easy-Button/&quot;&gt;good instructions&lt;/a&gt;)
and got rid of the speaker. I used some hookup wire to connect the
Easy button’s existing button circuitry to one of the input pins (20) and Ground
on the &lt;a href=&quot;https://www.pjrc.com/store/teensylc.html&quot;&gt;Teensy LC&lt;/a&gt;. To verify the button
was connected properly, I wrote a simple program for the Teensy that lit up the onboard
LED when there was input on pin 20.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/teensy_connections.jpg&quot; alt=&quot;Teensy connections&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The hardest part, by far, of the entire project was trying to fit and secure the new board
inside, and be able to close it back up. I also needed a hole in the case so the USB cable
could go from the Teensy to the computer.
Luckily I have a &lt;a href=&quot;http://www.dremel.com/en-us/Tools/Pages/ToolDetail.aspx?pid=200+Series&quot;&gt;Dremel tool&lt;/a&gt;,
which is perfect for this type of job. I used it to carve out a lot
of the internal plastic, and drilling a hole in the side for the cable. I got a little
creative and glued in a carved-up a
&lt;a href=&quot;http://www.homedepot.com/p/Safety-1st-Ultra-Clear-Plug-Protectors-18-Pack-HS230/205885675&quot;&gt;plug protector&lt;/a&gt;
I found in the junk drawer. This serves as a mount for the Teensy, so it won’t
rattle around inside.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/teensy_mount.jpg&quot; alt=&quot;Teensy mount&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The final, and easiest, step was to write the software for my new “keyboard”.
I used the &lt;a href=&quot;https://www.pjrc.com/teensy/td_download.html&quot;&gt;Teensyduino add-on&lt;/a&gt;
for the Arduino IDE, and set the USB Type to Keyboard. All Arduino programs (“sketches”)
consist of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup&lt;/code&gt; and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt; function. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup&lt;/code&gt; is run once, and is where
I configure the hardware pins. The Teensy LC’s onboard LED is available
on pin 13 - I configure that as an output (to aid debugging). Then I need
to configure pin 20 as an input (you’ll recall I soldered a wire from the button
to pin 20). The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt; function runs repeatedly, forever, while the device has power.
I use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Button&lt;/code&gt; library which nicely encapsulates the logic for detecting
button presses on an input pin. When the button is pressed, I turn on the LED
and then send the sequence of characters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:+1:&lt;/code&gt;, followed by Command+Enter
to submit the PR comment form (probably needs to be changed to ALT+Enter on Windows).
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Keyboard&lt;/code&gt; library handles all the details of sending the proper USB HID codes
to the computer. Full source code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/* Add +1 comment to Github Pull Request

   You must select Keyboard from the &quot;Tools &amp;gt; USB Type&quot; menu
*/&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;Bounce.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buttonPin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;debounceTime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//ms&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Bounce&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button20&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bounce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttonPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;debounceTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;


&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pinMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pinMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttonPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INPUT_PULLUP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;button20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallingEdge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digitalWrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HIGH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Keyboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;:+1:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// submit form (Command+Return)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Keyboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_LEFT_GUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Keyboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KEY_RETURN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Keyboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;releaseAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;risingEdge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()){&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digitalWrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I had a blast with this project, and its a great introduction to building a simple
device that can talk to a computer. Using the Teensy and a big button, you
can send anything that a USB mouse or keyboard can send. Think of the possibilities!
Special shout-out to &lt;a href=&quot;https://twitter.com/scichelli&quot;&gt;Sharon Cichelli&lt;/a&gt; for her
enthusiasm in showing how accessible and fun these hardware projects can be - hi Sharon!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/pr_button_parts.jpg&quot; alt=&quot;Work area with parts&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 07 Nov 2015 08:34:14 -0600</pubDate>
        <link>http://www.joshuaflanagan.com/blog/blog/2015/11/07/build-your-own-single-function-keyboard.html</link>
        <guid isPermaLink="true">http://www.joshuaflanagan.com/blog/blog/2015/11/07/build-your-own-single-function-keyboard.html</guid>
        
        
      </item>
    
      <item>
        <title>Infinity ErgoDox</title>
        <description>&lt;p&gt;I’ve always been picky about my keyboard, but recently discovered an entirely
new world of keyboard enthusiasts. &lt;a href=&quot;https://devchat.tv/ruby-rogues/200-rr-200th-episode-free-for-all-&quot;&gt;Aaron Patterson was on the Ruby Rogues podcast&lt;/a&gt;
talking about mechanical keyboard kits. As in, keyboards you build yourself.
You pick out the key switches (get just the right clicky feel), you pick out
the keycaps, you pick a layout, etc. And then you solder all the parts together.
That sounded pretty extreme to me! But I was just getting back into hardware
hacking (arduino, etc) and figured it would make for a fun project.&lt;/p&gt;

&lt;p&gt;Intrigued, I did some research, and discovered that Massdrop was just starting
an effort to build the &lt;a href=&quot;https://www.massdrop.com/buy/infinity-ergodox&quot;&gt;Infinity ErgoDox&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;an update to the popular ErgoDox.
Perfect, I placed an order (I went with Cherry MX Blue switches and blank DCS
keycaps, in case that means anything to you).
And waited. That was back in April. I pretty much
forgot about it until a box arrived from Massdrop a couple weeks ago.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/infinity_ergodox_parts.jpg&quot; alt=&quot;parts&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I finally got a rainy weekend to dedicate some time to it. Reading the forums,
people were saying that this was a much easier build than the ErgoDox, with one
mentioning a 20 minute build time. I think it took me 20 minutes to get all
my tools out and unwrap everything. This was not a cheap keyboard, the
parts are currently scarce, and most of the documentation seems to assume more
knowledge of the process than I had. But taking my time, soldering the key switches
to the PCB, installing the stabilizers, assembling the case, I had a working keyboard
about four hours later!
&lt;img src=&quot;/blog/assets/infinity_ergodox_assembled.jpg&quot; alt=&quot;a keyboard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Well, kinda. The hardware is only half of the story. The cool thing about the
Infinity ErgoDox is that it has a &lt;a href=&quot;https://github.com/kiibohd/controller&quot;&gt;completely customizable (open source) firmware&lt;/a&gt;.
Now that I have a device with a bunch of keys on it, I can decide exactly
what all of the keys do. It has an online configurator to build your customized
firmware for you, if all you want to do is re-map keys. But if you really want
to get fancy, you can build the firmware from source. This exposes all of the
capabilities of the device. Specifically, this keyboard kit includes a 128x32
LCD panel, as well as a controller to individually address each key’s backlight
LED (not included in the kit - bring your own fun colors).&lt;/p&gt;

&lt;p&gt;The best part is that there is a lot of unexplored territory. The existing firmware
code has some very crude support for the LCD and LEDs - just enough to prove that
they work. So there is a lot of room to flesh them out further, to try and support
all the silly things people might want to light up while they type. That’s the
part I am most excited about. Eventually, I’ll probably enjoy typing on it, too.&lt;/p&gt;
</description>
        <pubDate>Mon, 02 Nov 2015 17:40:31 -0600</pubDate>
        <link>http://www.joshuaflanagan.com/blog/blog/2015/11/02/infinity-ergodox.html</link>
        <guid isPermaLink="true">http://www.joshuaflanagan.com/blog/blog/2015/11/02/infinity-ergodox.html</guid>
        
        
      </item>
    
  </channel>
</rss>
