<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Portfolio]]></title><description><![CDATA[Cool snippets from my life.]]></description><link>https://alexhuang.me/</link><generator>Ghost 0.9</generator><lastBuildDate>Sun, 13 Jul 2025 08:45:43 GMT</lastBuildDate><atom:link href="https://alexhuang.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[DashFit]]></title><description><![CDATA[<p>For fitness reasons, I have been logging my diet and weight for most of the last 1.5 years. At first, I started with just paper and pen but quickly found it cumbersome to carry a notebook with me whenever I wanted to log. </p>

<p>I quickly moved on to using</p>]]></description><link>https://alexhuang.me/dashfit/</link><guid isPermaLink="false">b3d20536-6129-495e-ae80-38a37f83a409</guid><category><![CDATA[Projects]]></category><dc:creator><![CDATA[Alex Huang]]></dc:creator><pubDate>Sat, 21 Oct 2017 07:17:43 GMT</pubDate><media:content url="http://alexhuang.me/content/images/2017/10/dashfit-visualize-beta-1.png" medium="image"/><content:encoded><![CDATA[<img src="http://alexhuang.me/content/images/2017/10/dashfit-visualize-beta-1.png" alt="DashFit"><p>For fitness reasons, I have been logging my diet and weight for most of the last 1.5 years. At first, I started with just paper and pen but quickly found it cumbersome to carry a notebook with me whenever I wanted to log. </p>

<p>I quickly moved on to using Google Sheets to keep track of everything. This solved the issue of portability and even cross platform accessibility. However, as I continue to log every single day I have noticed these problems:</p>

<ol>
<li>Annoying to have to scroll through previous data to get to enter today's entry  </li>
<li>Can't keep a history of meals to avoid retyping  </li>
<li>Have to manually calculate 7 day average of weight  </li>
<li>Mobile app for sheets is buggy (sometimes doesn't load data past the first 1000 rows)  </li>
<li>Limited graphing option and graph layout isn't ideal for viewing </li>
</ol>

<p>Given that logging is now an important part of my life, I have decided to build a web app called DashFit to handle all the fitness related data input/storage/display.</p>

<h4 id="choosingadevelopmentstack">Choosing a development stack</h4>

<p>The first order of business is to choose a development stack. At the time of writing, there are more than a dozen popular development stacks. </p>

<p>From previous project experience, I believe it is important to start off with good code architecture to make maintenance and updates easy. Part of this comes from choosing the right stack.</p>

<p>In the UI department, one library that stands out is React. Treating your UI as reusable modules will aid in clarity and long term maintainability. A downside from using React is that it requires building/pre-processing. </p>

<p>I want to keep the build tools as simple as possible, since many of the fancier tools go out of date fairly quickly and have a steep learning curve. My build tool of choice is <a href="https://webpack.github.io/">WebPack</a>, which is simple to use and not hard to learn. The idea behind WebPack is elegant: imagine your dependencies as a tree where each node is a module and edges are <code>require</code>s, you basically provide it the root (react file where you do all the <code>requires</code>) and it traverses the tree until it loads all the dependencies and their respective dependencies. </p>

<p>In terms of the back end, I see no reason to move away from Express and mongoDB. So all in all, I am using the MERN stack (mongo, express, react, node).</p>

<h4 id="thinkinginreact">Thinking in React</h4>

<p>Using React is like learning web development all over again. The thinking in React is very different from any UI work I have done before and one such aspect is styling. </p>

<p>React seems to <del><a href="https://medium.com/yplan-eng/inline-styles-are-so-2016-f100b79dafe1#.mlyv7ju4m">advocate</a></del>(they have since taken down the article as of March 2017) inline styling, something that I do not agree with - so I will instead use LESS and style elements like I have always done. However, I also see value in React's way of thinking - which is to keep components their own respective, independent unit including its own styling. </p>

<p>As such, I will use LESS as a preprocessor and organize my file structure such that each component has its own stylesheet in development that gets bundled together for production. </p>

<p>Eg.  </p>

<pre><code>|components
  |Header
    |Header.jsx
    |Header.less
  |Nav
  |Container
  |Footer
</code></pre>

<p>Notice that the react code also lives in its own folder. WebPack will bundle these as well for production.</p>

<h4 id="features">Features</h4>

<ol>
<li>User authorization system <br>
<ul><li>Use Passport.js to support email login</li></ul></li>
<li>Weight logging <br>
<ul><li>Table view of weight for the week</li>
<li>Ability to view and edit week data</li>
<li>Undo redo</li>
<li>Accept kg. and lb. input  </li></ul></li>
<li>Diet logging <br>
<ul><li>Table view of daily caloric intake for the day and week</li>
<li>Ability to store custom recipes and their calories/protein</li>
<li>Auto complete input based on previous recipes</li></ul></li>
<li>Data visualization <br>
<ul><li>Graph weekly average of weight</li></ul></li>
</ol>

<h4 id="update1102117">Update 1 (10/21/17):</h4>

<p>It's been a while but I have been implementing the aforementioned feature throughout the summer. The code can be found on <a href="https://github.com/al3x-huang/DashFit">github</a>. </p>

<p>The original feature list now looks like:</p>

<ol>
<li><del>User authorization system</del> <br>
<ul><li><del>Use Passport.js to support email login</del></li></ul></li>
<li>Weight logging <br>
<ul><li><del>Table view of weight for the week</del></li>
<li><del>Ability to view and edit week data</del></li>
<li>Undo redo</li>
<li>Accept kg. and lb. input  </li></ul></li>
<li>Diet logging <br>
<ul><li>Table view of daily caloric intake for the <del>day</del> and week</li>
<li>Ability to store custom recipes and their calories/protein</li>
<li>Auto complete input based on previous recipes</li></ul></li>
<li>Data visualization <br>
<ul><li><del>Graph weekly average of weight</del></li></ul></li>
</ol>

<p>So I would say that the core features are implemented but the bells and whistles should still be added on at some point. </p>

<p>Here is what the webpages look like as of now:</p>

<p><img src="https://alexhuang.me/content/images/2017/10/dashfit-weightlog-beta.png" alt="DashFit"></p>

<p>This is the first page that I ended up implementing. I wanted the UI to have a modern, lightweight feel so lots of whitespace and simplicity is what I ended up going with. </p>

<p>For styling, I used <a href="http://getskeleton.com/">skeleton</a> as a starting point and LESS as my preprocessor. React is amazingly fast thanks to their virtual DOM diffing process. Lastly, for layout I went for a standard dashboard theme. This design was highly inspired by the dashboard template for Bootstrap but I ended up building the website from grounds up. This is the initial layout I was going with:</p>

<p><img src="https://alexhuang.me/content/images/2017/10/ui-prototyping.jpg" alt="DashFit"></p>

<p>You could probably see the similatiry between that and the current design, except I stripped away the color scheme in favor of a flatter tone. </p>

<p>React's modular nature also made it easy to organize components. For each tab on the left (log weight, visualize, log meals), I have defined  "widget" that acts as a kind of scaffolding that calls all the components in the page and brings them all to a functional "sub-app". </p>

<p><img src="https://alexhuang.me/content/images/2017/10/dashfit-visualize-beta.png" alt="DashFit"></p>

<p>For this part, I used the react plotting library <a href="https://github.com/recharts/recharts">Recharts</a>. This library had some issues that I ended up actually helping identify but for personal project plotting I think it works well enough but I would be hesistant using it in a production environment.</p>

<p>Pictured above is my weight trend for the last ~2 years. The purple line is the daily weight and the green line is the weekly average. </p>

<p><img src="https://alexhuang.me/content/images/2017/10/dashfit-meal-log-beta.png" alt="DashFit"></p>

<p>At this point, I was fed up with the way states were kept. Specifically, they have to "bubble" up to a parent component. </p>

<p>Thankfully, React has a solution for this: <a href="https://facebook.github.io/flux/">Flux</a>! I implemented the meal log using this and I must say: its design philosophy is simply elegant and makes building large UIs much more manageable. </p>

<p>Additionally, it makes code more readable and less likely to fail from improper handling of data. </p>

<p>Right now, I am thinking about refactoring the first two parts of the code using <a href="https://facebook.github.io/flux/">Flux</a> so will likely implement the missing features when I find time for that. </p>]]></content:encoded></item><item><title><![CDATA[Adafruit ESP 32 Development Board Setup]]></title><description><![CDATA[A tutorial for setting up the tool chain, making a hello world program, and flashing it to an Adafruit ESP32 development board for OSX Yosemite.]]></description><link>https://alexhuang.me/adafruit-esp-32-development-board-setup/</link><guid isPermaLink="false">73e75407-62c9-4ad3-a4d9-eb1afac05dc6</guid><dc:creator><![CDATA[Alex Huang]]></dc:creator><pubDate>Thu, 08 Jun 2017 17:59:01 GMT</pubDate><content:encoded><![CDATA[<p>Instructions are unclear on Adafruit's website regarding how to set this board up, so I decided I would document the steps I took to get <code>HelloWorld</code> working on this development board. </p>

<p>Technical details: <br>
Board: Adafruit Espressif ESP32 <a href="https://www.adafruit.com/product/3269">Development Board</a> - Developer Edition <br>
OS: OSX Yosemite 10.10.5</p>

<h3 id="step1">Step 1:</h3>

<p>Download the Espressif pre built <a href="http://esp-idf.readthedocs.io/en/latest/get-started/macos-setup.html">Xtensa Toolchain</a> for OSX by visiting the page and looking for the download link. This page should have the latest tool chain. </p>

<p>Run  </p>

<pre><code>mkdir -p ~/esp  
cd ~/esp  
tar -xzf ~/Downloads/xtensa-esp32-elf-osx-1.22.0-61-gab8375a-5.2.0.tar.gz  
</code></pre>

<p><strong>Note</strong>: If you substituted <code>~/esp</code> with another directory of your choosing, make sure that there is no space in the path and for the rest of the guide you reference what you used in place of <code>~/esp</code>. Additionally, your toolchain version may differ from mine so make sure you modify the command appropriately. </p>

<p>Then, to make sure that Terminal can find the binaries, we have to update the PATH variable:</p>

<pre><code>echo '#Adding path variable for ESP32 development' &gt;&gt; ~/.bash_profile  
echo 'export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin' &gt;&gt; ~/.bash_profile  
source ~/.bash_profile  
</code></pre>

<p><strong>Note</strong>: If you used a different directory for <code>~/esp</code>, replace <code>$HOME/esp</code> with your own.</p>

<p>Now, type in <code>xt</code> and press tab a few times you should see something along the lines of <code>xtensa-esp32-elf-xxx</code>. If nothing happens or you don't see anything like that, then your PATH has not been set up correctly. </p>

<h3 id="step2">Step 2:</h3>

<pre><code>cd ~/esp  
git clone --recursive https://github.com/espressif/esp-idf.git  
</code></pre>

<p><strong>Note</strong>: --recursive is critical, otherwise you have to update the submodules yourself. </p>

<h3 id="step25">Step 2.5:</h3>

<p>Pause here. It is important to note that the ESP-IDF build system does not support spaces in esp-idf or project paths. You will end up getting weird errors otherwise. </p>

<h3 id="step3">Step 3:</h3>

<p>The Adafruit ESP32 development board comes with a USB&lt;--->UART module; namely, the SILABS <a href="https://www.silabs.com/documents/public/data-sheets/CP2102-9.pdf">CP2102</a>. In order to get this to interface with our Mac, we must install the appropriate <a href="http://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers">driver</a>. </p>

<p>Scroll down and download the one for OSX and click through the installation. </p>

<p>After that, plug in your board via USB, open up Terminal, and type in:  </p>

<pre><code>ls /dev/tty.*  
</code></pre>

<p>You should see something along the lines of  </p>

<pre><code>/dev/tty.SLAB_USBtoUART
</code></pre>

<h3 id="step4">Step 4:</h3>

<p>We will now get our ESP32 to print hello world to us via serial. First, we grab some example code from esp-idf:</p>

<pre><code>cp -r ~/esp/esp-idf/examples/get-started/hello_world/ ~/esp/ESP32/HelloWorld  
cd ~/esp/ESP32/HelloWorld  
</code></pre>

<p>Make sure we set the correct path for ESP-IDF:  </p>

<pre><code>export IDF_PATH=~/esp/esp-idf  
</code></pre>

<p>Run the terminal interface with the command:  </p>

<pre><code>make menuconfig  
</code></pre>

<p>Then use your arrow key to go to Serial flasher config -> (xxx) Default serial port then type in the serial port that the ESP32 is connected to from step 3. For me, this is <code>/dev/tty.SLAB_USBtoUART</code></p>

<p>Exit and save the config. </p>

<p>Run <code>make</code> and you should see the build process. </p>

<p>As an Aside: I got a warning of:</p>

<pre><code>WARNING: Toolchain version is not supported: crosstool-NG crosstool-ng-1.22.0-53-g46f160f-dirty  
Expected to see version: crosstool-NG crosstool-ng-1.22.0-61-gab8375a  
Please check ESP-IDF setup instructions and update the toolchain, or proceed at your own risk.  
</code></pre>

<p>which meant that I got the wrong toolchain version because I was following ESP's out of date version of documentation. This has since been fixed and I have updated the guide accordingly. I will just leave this here for reference in case others run into the same issue. </p>

<p>If all went well, you should get a hint at the end of the compile telling you how to flash to the board:</p>

<pre><code>&gt; make flash
Flashing binaries to serial port /dev/tty.SLAB_USBtoUART (app at offset 0x10000)...  
esptool.py v2.0-beta3  
Connecting........__  
Uploading stub...  
Running stub...  
Stub running...  
Configuring flash size...  
Auto-detected Flash size: 4MB  
Flash params set to 0x0220  
Compressed 15872 bytes to 9318...  
Wrote 15872 bytes (9318 compressed) at 0x00001000 in 0.8 seconds (effective 154.3 kbit/s)...  
Hash of data verified.  
Compressed 355216 bytes to 167627...  
Wrote 355216 bytes (167627 compressed) at 0x00010000 in 14.8 seconds (effective 192.7 kbit/s)...  
Hash of data verified.  
Compressed 3072 bytes to 82...  
Wrote 3072 bytes (82 compressed) at 0x00008000 in 0.0 seconds (effective 2150.1 kbit/s)...  
Hash of data verified.

Leaving...  
Hard resetting...  
</code></pre>

<p>This means that we have successfully flashed HelloWorld to our board. To check if we really succeeded, run <code>screen /dev/tty.SLAB_USBtoUART 115200</code> and look at the output. This is what I got:</p>

<pre><code>Restarting in 3 seconds...  
Restarting in 2 seconds...  
Restarting in 1 seconds...  
Restarting in 0 seconds...  
Restarting now.  
E (11211) wifi: esp_wifi_stop 802 wifi is not init  
ets Jun  8 2016 00:22:57  
...
...
...
I (1121) cpu_start: Starting scheduler on PRO CPU.  
Hello world!  
I (201) cpu_start: Starting scheduler on APP CPU.  
This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 0, 4MB external flash  
Restarting in 10 seconds...  
</code></pre>

<p>Congratulations, you have successfully set up the build environment for the ESP32 and flashed it. You are now well on your way to building the next awesome IOT project!</p>]]></content:encoded></item><item><title><![CDATA[CrossPack Tutorial]]></title><description><![CDATA[<h3 id="programmingmictrocontrollerwithoutarduino">Programming Mictrocontroller Without Arduino</h3>

<p>Programming with the Arduino IDE and utilizing its included libraries is nice, but oftentimes Arduino abstracts away crucial details that have to be accounted for in more complicated projects. I thought it would be a good opportunity to move closer to the hardware level and to</p>]]></description><link>https://alexhuang.me/crosspack-tutorial/</link><guid isPermaLink="false">920acf74-a64a-4a2d-8b1b-07f6af757d6a</guid><category><![CDATA[Projects]]></category><dc:creator><![CDATA[Alex Huang]]></dc:creator><pubDate>Tue, 22 Nov 2016 13:03:06 GMT</pubDate><content:encoded><![CDATA[<h3 id="programmingmictrocontrollerwithoutarduino">Programming Mictrocontroller Without Arduino</h3>

<p>Programming with the Arduino IDE and utilizing its included libraries is nice, but oftentimes Arduino abstracts away crucial details that have to be accounted for in more complicated projects. I thought it would be a good opportunity to move closer to the hardware level and to program the AVR microcontroller in C for my upcoming project, using command line utilities neatly packaged by <a href="https://www.obdev.at/products/crosspack/index.html">CrossPack</a>. </p>

<p>As a test, I wrote a simple script targeted for an ATTiny85 to output a 50 Hz square wave on one of its pins using the template from running <code>avr-project Demo</code>:  </p>

<pre><code>#include &lt;avr/io.h&gt;
#include &lt;util/delay.h&gt;

int main(void)  
{
    DDRB = 0x01;    //Set PB0 as output
    for(;;){
        PORTB ^= 0x01;  //Toggle PB0 
        _delay_ms(10);
    }
    return 0;   /* never reached */
}
</code></pre>

<p>The <code>makefile</code> configuration that came with CrossPack's demo template worked extremely well in simplifying the compile and flashing process, the changes I had to make were the following lines (note that your programmer may appear differently in your file system than mine, but it should be along the lines of /dev/tty.* for OSX):  </p>

<pre><code>DEVICE     = attiny85  
CLOCK      = 8000000  
PROGRAMMER = -c stk500v1 -b 19200 -P /dev/tty.usbmodem1411 #Settings for ArduinoISP  
OBJECTS    = main.o  
FUSES      = -U hfuse:w:0xdf:m -U lfuse:w:0xe2:m    #default fuses for ATtiny85 without clock division  
</code></pre>

<p>Hints: </p>

<ul>
<li>use <code>avrdude -p ?</code> to list the supported AVR devices.</li>
<li>find the Arduino ISP using <code>ls /dev/tty.*</code></li>
<li>you MUST use <code>-c stk500v1</code> and provide the baud rate of <code>19200</code> if using Arduino as programmer</li>
<li><a href="http://www.engbedded.com/fusecalc">fuse calcululator</a></li>
</ul>

<p>To program an AVR chip, you must have a programmer. A popular choice is something like the AVR <a href="https://www.sparkfun.com/products/9825">pocket programmer</a>, but if you're like me and don't want to wait the shipping, an Arduino Uno can actually be programmed to be a programmer that you likely have around the shop! So, the first order of business is to flash the Arduino with the <code>ArduinoISP</code> (ISP stands for in-system programmer) sketch from File->Examples. Then, we connect the Uno like so to the Tiny:</p>

<p><img src="https://alexhuang.me/content/images/2016/10/ATTiny85-Test.svg" alt=""></p>

<p>The command <code>make flash</code> produced the following:  </p>

<pre><code>avrdude -c stk500v1 -b 19200 -P /dev/tty.usbmodem1411 -p attiny85 -U flash:w:main.hex:i

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e930b  
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed  
         To disable this feature, specify the -D option.
avrdude: erasing chip  
avrdude: reading input file "main.hex"  
avrdude: writing flash (78 bytes):

Writing | ################################################## | 100% 0.18s

avrdude: 78 bytes of flash written  
avrdude: verifying flash memory against main.hex:  
avrdude: load data flash data from input file main.hex:  
avrdude: input file main.hex contains 78 bytes  
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.09s

avrdude: verifying ...  
avrdude: 78 bytes of flash verified

avrdude: safemode: Fuses OK (H:FF, E:DF, L:E2)

avrdude done.  Thank you.  
</code></pre>

<p>Upon checking the fuse, it turns out that the version of avrdude that came in CrossPack is the version that had a <a href="http://www.avrfreaks.net/forum/hfuse-and-efuse-swapped-avrdude">label typo</a> when displaying the fuse values at the end, so it should really read: <code>Fuses OK (E:FF, H:DF, L:E2)</code>. </p>

<p>The code above used up a total of 164 bytes of flash, whereas the same code (functionally) written using Arduino API:</p>

<pre><code>void setup() {  
  pinMode(8,OUTPUT);
}

void loop() {  
  digitalWrite(8,~digitalRead(8));
  delay(10);
}
</code></pre>

<p>resulted in a 932 bytes of flash usage. That's a substantial difference especially when we're working with devices equipped with only tens of Kbytes of flash. </p>

<p>So be brave, go out there and program your AVRs with the command line utilities and free yourself from the chains of Arduino. </p>]]></content:encoded></item><item><title><![CDATA[Convergence Meter]]></title><description><![CDATA[<p>Convergence meter is a single digit display device that can be purposed to elegantly present any numerical information. </p>

<p>The anniversary for me and my girlfriend was coming up, so I figured to give a unique gift, I would build this meter. Additionally, I couldn't say no to working with high</p>]]></description><link>https://alexhuang.me/convergence-meter/</link><guid isPermaLink="false">f869fd63-13af-42e2-bcb4-61fb50cbbf00</guid><category><![CDATA[Projects]]></category><dc:creator><![CDATA[Alex Huang]]></dc:creator><pubDate>Fri, 12 Aug 2016 18:06:00 GMT</pubDate><media:content url="http://alexhuang.me/content/images/2016/08/Nixie_Tube-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://alexhuang.me/content/images/2016/08/Nixie_Tube-1.jpg" alt="Convergence Meter"><p>Convergence meter is a single digit display device that can be purposed to elegantly present any numerical information. </p>

<p>The anniversary for me and my girlfriend was coming up, so I figured to give a unique gift, I would build this meter. Additionally, I couldn't say no to working with high voltage and soviet era technology in this project.</p>

<p>The significance in an anniversary commemorating the amount of time that you have spent with a person. Therefore, Convergence Meter is, in this case, going to display the number of days since meeting her. </p>

<p>I chose to use an IN-14 Nixie tube for this task because of its warm, unique glow that never failed to capture attention. Also, Nixie tubes have a very interesting history of being used in old school scientific instruments and military equipment back before LCDs were a thing. </p>

<p>The particular tube I got (on eBay) was from Ukraine and according to the markings on the tube, made in 1977 in the Soviet Union. It even had the CCCP stamp of authenticity! <br>
<img src="https://alexhuang.me/content/images/2016/08/CCCP-Seal.jpg" alt="Convergence Meter"></p>

<h3 id="testingthetube170volts">Testing the tube: 170 Volts!</h3>

<p>The first order of business was to light this baby up to check that it is still indeed in working order after all these years and the shipping process. </p>

<p>To strike the tube, we need a high voltage of 170+ Volts to ionize the gas molecules. After this happens, the ions will be attracted towards the negatively charged number wire (cathode), and the resulting collision between said ions and said number wire will expel larger metal atoms. Electrons from the cathode itself are also attracted to the positively charged outside wire mesh (anode) and subsequently can collide and energize electrons from the expelled metal atoms. Upon collision, the electron in the metal atom gains energy and moves to a higher energy state and when it stabilizes and comes back down to the default energy state, that energy is converted to light. For a more detailed description, read this great <a href="http://www.explainthatstuff.com/how-nixie-tubes-work.html">article</a> about how Nixie tubes work.</p>

<p>The first challenge was in obtaining 170+V, a non-trivial task. Linear bench power supplies usually don't go much past 50V, so I decided to go with a switching boost converter. In the future, I plan on building my own converter but in the interest of time, I used an existing <a href="http://www.lumos.sk/Power-Supply-180V">kit</a> that was readily available on eBay. </p>

<p>The kit came with a completely unpopulated board,  the necessary passives and ICs, as well as clear instructions: <br>
<img src="https://alexhuang.me/content/images/2016/08/Power-Supply.png" alt="Convergence Meter"></p>

<p>After about ~30 minutes of soldering, ensuring the orientation of the ICs were correct, I finished the assembly:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/Power-supply-assembled.jpg" alt="Convergence Meter"></p>

<p>The converter took 10-18V DC and converted it to 110-180V DC set by a trim potentiometer. After 12V was fed to the converter and it passed the smoke test, I played with the pot, ensuring I saw 170V at the output. </p>

<p>Then, the moment of truth, time to give the tube some electricity. I used some nifty test <a href="http://catalog.e-z-hook.com/category/test-hooks?">hook probes</a> to attach  ground to the number "7" cathode and 170V to the anode WITH a 10k current limiting resistor in series like so: </p>

<p><img src="https://alexhuang.me/content/images/2016/08/block-diagram-testing.jpg" alt="Convergence Meter"></p>

<p>To figure out the value of CLR (current limiting resistor) you need, first look up the voltage drop across your Nixie when it's struck (for an IN-14, the relevant information can be found on this <a href="http://www.tube-tester.com/sites/nixie/data/in-14/in-14.htm">site</a>). Since the typical maintaining voltage is 145V and supply voltage is 170V and we want 2.5 mA to flow through the tube (assume tube has very little resistance when struck) we can use the following relation to figure out the CLR value: </p>

<p>$$R=\frac{\Delta{V}}{I}=\frac{(170-145)\text{ Volts}}{\frac{2.5}{1000}\text{ Amps}} $$ $$= 10 \text{ k}\Omega$$</p>

<p>And... let there be light!</p>

<p><img src="https://alexhuang.me/content/images/2016/08/Nixie_Tube-2.jpg" alt="Convergence Meter"></p>

<p>The picture doesn't really do the tube much justice, as the limited dynamic range of my camera doesn't capture the full glory and warmth of the tube's glow. It's just something you have to see for yourself. </p>

<h3 id="betterfixtureforthetube">Better Fixture for the Tube</h3>

<p>Now that we confirmed the tube is working, we can start to prototype with it! However, attaching test probes for all 11 connections is a hassle, so we should use a breakout board. I looked around online for existing breakouts but there seemed to only be boards for IN-12 tubes. So, I set out to design my own with the following goals:</p>

<ol>
<li>Compatible with 0.1'' breadboard spacing  </li>
<li>Swap tubes without soldering, so need some kind of receptacle  </li>
<li>Current limiting resistor on board</li>
</ol>

<p>After several iterations, I settled with the following design in Eagle CAD:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/breakout_design.jpg" alt="Convergence Meter"></p>

<p>As expected, there was no library part for the IN-14 tube so I had to create that part myself. With the help of <code>cmd-draw.ulp</code>, I was able to get the pads in a circular pattern. Here's a <a href="https://www.youtube.com/watch?v=cIiVNqW4VWg">video</a> that shows how it's done. </p>

<p>The next tricky part was satisfying design goal 2: be able to swap out tubes easily. I had to order some tiny receptacles from Digi-Key as the parts were too specialized for eBay. To determine the dimensions we needed, I measured the Nixie tube pin diameter, which was 0.5 mm. Then, I looked for the receptacle with the greatest depth, which was about 1/8'' or 3mm. After ordering the <a href="https://www.digikey.com/product-detail/en/harwin-inc/H3153-01/952-1457-ND/2264438">receptacles</a> and sending out the boards to Smart Prototyping, it was time to wait.</p>

<p>(I will put up the design files on Portfolio as soon as I sort out file hosting. For now, if you are interested in getting some of these boards just <a href="mailto:alexh95@mit.edu"> shoot me an email</a>)</p>

<p>After about 10 days, my boards showed up: <br>
<img src="https://alexhuang.me/content/images/2016/08/boards_arrived.jpg" alt="Convergence Meter"></p>

<p>This was my first time using Smart Prototyping and  for only $34 I was fairly impressed with the speed. The quality isn't as good as OSHPark but it shaved about 4-5 days from the turn time. </p>

<p>After populating the PCB and trimming+straightening the leads from the tubes, I got this:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/Tube-and-board.jpg" alt="Convergence Meter"></p>

<p><img src="https://alexhuang.me/content/images/2016/08/breakout-assembled.jpg" alt="Convergence Meter"></p>

<p>The tube sat firmly in the receptacles. You could dangle the whole thing upside down and the tube would not come loose. So far so good. </p>

<h3 id="microcontrollertimehardware">Microcontroller Time: Hardware</h3>

<p>Now that we had the Nixie tube and its power source set up, we needed to give it some life by interfacing it with a microcontroller. For the purpose of getting this done quickly, I used the ATmega328p based Arduino Uno to prototype and will eventually use the standalone ATmega328p chip. </p>

<p>The diagram below shows the initial block design: <br>
<img src="https://alexhuang.me/content/images/2016/08/block-diagram-rtc-1.jpg" alt="Convergence Meter"></p>

<p>To prototype, we first build the circuit on a breadboard, then design a PCB after we confirm everything is working. Things to note:</p>

<ul>
<li>I won't be using the buck converter for the breadboard prototype as my bench power supply will be able to deliver 5V as well as 12V.</li>
<li>The 74141 chip is out of production and hard to find nowadays. Instead, I will use a much more readily available <a href="http://tubehobby.com/datasheets/k155id1.pdf">K155ID1</a> Russian equivalent. </li>
<li>The breakout board that will be used in the breadboard prototype is from the first design iteration, so it will appear different from the breakout seen above and the one used in the final product.</li>
</ul>

<p>After a couple hours at the bench following the diagram, cutting wires, and soldering:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/breadboard-prototype.jpg" alt="Convergence Meter"></p>

<p>To get 5V and 12V, I used a bench supply that I built using a discarded PC ATX power supply:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/power-supply.jpg" alt="Convergence Meter"></p>

<h3 id="microcontrollertimesoftware">Microcontroller Time: Software</h3>

<p>In order to drive the tube in an interesting manner, we will have to play around with the software a little. Recall that at the very beginning, we set out the goal that Convergence Meter will be a 1 tube display for the amount of time that has passed since meeting your significant other/friend/someone important to you.  The following goals will more specifically define how we want to display the time: </p>

<ol>
<li><p>When triggered with a switch, the display should flash a sequence of numbers representing the days that have passed since meeting a person.</p></li>
<li><p>In its idle state (not triggered), the tube should  display the current time's second's ones place. For example, if the time is 3:15:47 PM then the tube should display a 7. Additionally, in the idle state, the tube should fade between new numbers, so going from 6 to 7 would show 6 fading out while 7 simultaneously fading in. This functionality should be implemented using a timer interrupt PWM where the switching cycle is fast enough to fool the eye into thinking it's smooth fading. This approach leave our main loop plenty of time to do other tasks. </p></li>
<li><p>During the transition from idle to triggered, the meter should do something interesting. I have chosen a fading in and out of random numbers for the transition period. </p></li>
</ol>

<p>Here is a software block diagram to show how the program should be structured:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/software-diagram-1.svg" alt="Convergence Meter"></p>

<p>The obvious constraint with this software design is that the interrupt has to be fast enough to fool the human eye into smoothing out the PWM of the tube, but leave enough time for the main loop to do its tasks. Therefore, I chose to have the switching period be 55 Hz, which should be plenty fast to fool the eye. The interrupt also had to be kept pretty lean in order to ensure that the main loop has time. As a result, the interrupt routine is partially written using direct port manipulation, which should save us a lot of cycles at the cost of readability. </p>

<p>I wrote the code according to the diagram above and added a line to flip the state of a pin every time the interrupt is called and checked the following on the oscilloscope:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/Interrupt-sqw.jpg" alt="Convergence Meter"></p>

<p>This translates to an interrupt frequency of \( 2 \cdot 1.785 = 3.57 \text{ kHz}\) (the factor of 2 comes from the fact that the frequency on the scope is comprised of 2 interrupt calls). To figure out the switching frequency, we simply take into account of the number of brightness levels we have. So for 64 brightness levels: </p>

<p>$$ 3.57 \text{ kHz} \cdot \frac{\text{switch cycle}}{64 \text{ brightness levels}} $$</p>

<p>$$ \approx 55 \frac{\text{switch cycle}}{\text{second}}$$</p>

<p>Which is plenty fast for fading our Nixie tube.</p>

<p>The full code can be found at <a href="https://github.com/al3x-huang/convergence-meter">github</a>.  I've gone ahead and included plenty of comments so it should be straightforward to follow.</p>

<p>After uploading to the Uno and debugging, I got the Uno talking to the RTC and manipulating the K155ID1, fading the Nixie in and out. Here is a picture of the tube fading from a 3 to a 4:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/nixie-fading.jpg" alt="Convergence Meter"></p>

<h3 id="somethingmorepermanentpcb">Something More Permanent: PCB</h3>

<p>Now that the prototype is completed and we have successfully implemented the required functionality in hardware and software, it is time  to move on from the breadboard prototype to something more suited for production: a PCB. </p>

<p>Using the same schematic as the one we used to build the breadboard, I created a PCB that featured the Uno's microcontroller along with everything else from the breadboard prototype:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/smd_board_schem.svg" alt="Convergence Meter"></p>

<p>and after some work with placing/routing the board: </p>

<p><img src="https://alexhuang.me/content/images/2016/08/smd_board.png" alt="Convergence Meter"></p>

<p>I focused on reducing board size as that decreased cost of production. The routing for the 74141N/K155ID1 was pretty tricky. I could have used SMD resistors and capacitors but since I have access to through hole passives for free from the MIT EE lab, I chose to use those. </p>

<p>For this board run, I sent it out to OSHPark as I didn't need that many copies and it would be less than 4$ per board for an order of 3. </p>

<p>While waiting for the miniature board to arrive, I also created a single sided version of the board for fun/self etching. I was pretty proud of the fact that I got the board routed without using any jumper wires:</p>

<p><img src="https://alexhuang.me/content/images/2016/08/th_board.png" alt="Convergence Meter"></p>

<p>Since space wasn't a constraint for the single sided run, I went with the through hole ATmega328P chip. I etched the board and soldered the components and it came out pretty well, but the boards from OSHPark showed up before I had time to test the single sided boards. </p>

<p>Here are the boards from OSHPark: </p>

<p><img src="https://alexhuang.me/content/images/2016/08/smd_board_bare.jpg" alt="Convergence Meter"></p>

<p><img src="https://alexhuang.me/content/images/2016/08/smd-board-populated.jpg" alt="Convergence Meter"></p>

<p>The board was tested and proved to work. The next step was to put everything we had built into a nice package. </p>

<h3 id="enclosuredesign">Enclosure Design</h3>

<p>To enclose everything, I chose to build a box out of laser cut 1/8'' plywood. The main concern with the enclosure is that it has to be stable enough for the user to be able to press the button without tipping, so the longest dimension of the box should not be in the vertical plane. </p>

<p>I did a rough layout of the various components (buck converter, main board, boost converter) and measured roughly how wide/deep the box would have to be. The height was estimated by inspection, mostly to give enough clearance for the wires that I would run from the switch and nixie tube to the breakout board.</p>

<p>With the help of <a href="http://www.makercase.com/">MakerCase</a>, I got an SVG file for the sides of the finger joint box after I inputted the required dimensions. To complete the design, I converted the SVG into a DXF file, imported that into Autodesk inventor, added some T-slots (note you can add t-slots on MakerCase but the settings menu was not flexible enough to generate exactly what I wanted), and incorporated the necessary mounting holes for the switch, tube, and 12V barrel connector. </p>

<p>Then, I exported the drawing from Inventor as a DXF and fed it over to the MIT Hobby Shop laser cutter. This is the result:</p>

<p><img src="https://alexhuang.me/content/images/2016/09/laser-cutting.jpg" alt="Convergence Meter"></p>

<p><img src="https://alexhuang.me/content/images/2016/09/laser-cutted.jpg" alt="Convergence Meter"></p>

<p><img src="https://alexhuang.me/content/images/2016/09/box-test-assembly.jpg" alt="Convergence Meter"></p>

<h3 id="puttingitalltogether">Putting it all together</h3>

<p>At this point, we have all the necessary pieces to complete the project and it is a matter of assembly. First, I tried fitting the electronics without any tape/wires:</p>

<p><img src="https://alexhuang.me/content/images/2016/09/test-fit.jpg" alt="Convergence Meter"></p>

<p>The fit was pretty much expected. so it was time to put in the tube, switch, and wiring and throw some double sided tape on the PCBs to keep them from rattling around. </p>

<p><img src="https://alexhuang.me/content/images/2016/09/fit-wiring.jpg" alt="Convergence Meter"></p>

<p>I ended up modifying the configuration a little bit to give the wires coming from the 12V barrel connector a little more room, but everything fit nicely. </p>

<p>Upon first closing the lid and powering up the meter, I noticed that the hardware interrupt service would be triggered at random times. After debugging, I noticed the problem would go away when I removed the wires coming from the switch, so they must have been picking up some EMI from the boost converter's inductor switching at high frequency. This is a somewhat hacky solution, but I ended up wrapping the wires in aluminum foil and putting a thick sheet of folded foil insulated with electrical tape between the boost converter and the wire leads for shielding:</p>

<p><img src="https://alexhuang.me/content/images/2016/09/meter-shielded.jpg" alt="Convergence Meter"></p>

<p>The problem was solved, although it was cool to see convergence triggering at random times. It might be something to consider implementing in software at a later time!</p>]]></content:encoded></item><item><title><![CDATA[Building My Portfolio!]]></title><description><![CDATA[<div class="derp"></div>  

<p><img src="https://upload.wikimedia.org/wikipedia/commons/f/fa/Ghost-Logo.svg" alt="">
After much deliberation, considering possibilities from building my entire portfolio platform from scratch to using WordPress, I've finally decided on using Ghost to build my portfolio. </p>

<p>The reasoning is as follows:</p>

<ol>
<li><p>I need to get this portfolio up fairly quickly, so I can start documenting the projects lined up this</p></li></ol>]]></description><link>https://alexhuang.me/building-my-portfolio/</link><guid isPermaLink="false">3eed5cc5-0e69-40de-9a46-14c20a351059</guid><category><![CDATA[Getting Started]]></category><category><![CDATA[Projects]]></category><dc:creator><![CDATA[Alex Huang]]></dc:creator><pubDate>Fri, 01 Jul 2016 18:48:42 GMT</pubDate><media:content url="https://upload.wikimedia.org/wikipedia/commons/f/fa/Ghost-Logo.svg" medium="image"/><content:encoded><![CDATA[<div class="derp"></div>  

<img src="https://upload.wikimedia.org/wikipedia/commons/f/fa/Ghost-Logo.svg" alt="Building My Portfolio!"><p><img src="https://upload.wikimedia.org/wikipedia/commons/f/fa/Ghost-Logo.svg" alt="Building My Portfolio!">
After much deliberation, considering possibilities from building my entire portfolio platform from scratch to using WordPress, I've finally decided on using Ghost to build my portfolio. </p>

<p>The reasoning is as follows:</p>

<ol>
<li><p>I need to get this portfolio up fairly quickly, so I can start documenting the projects lined up this summer.</p></li>
<li><p>Ghost is open source, well maintained, and written in Javascript, which I am more familiar with than PHP (WordPress). </p></li>
<li><p>The front end creation process seems to be well streamlined and can be learned fairly quickly, which will allow me to create a custom UI to my liking. Currently, there are plans for 2 sections - my projects as well as my travels but I am sure this is bound to expand in the future as my hobbies change. The portfolio has to be able to adapt to this.</p></li>
</ol>

<p>I will be working on completing the front end in the coming days. </p>

<p>Update 1:</p>

<p>So I bumped into the first hurdle while building the front end today. There is a design philosophy known as "<a href="https://en.wikipedia.org/wiki/Progressive_enhancement">progressive enhancement</a>", meaning that ideally anyone on any browser should be able to access the "basic content and functionality" of the page. </p>

<p>Apparently, there is about <a href="http://stackoverflow.com/questions/9478737/browser-statistics-on-javascript-disabled">1%</a> of users who don't have Javascript enabled and as a believer of progressive enhancement, I had to come up with a solution. The UI I designed relies on JQuery to do some initial formatting in order to account for the nav bar at the top. If the user did not have JS enabled, then s/he would have a hard to seeing the blog title, as it would be partially hidden under the nav bar. </p>

<p>To accommodate the 1%, I have decided to remove the static nav bar feature, eliminating the need to javascript intervention. To achieve this, I associated a class of <code>no_js</code> to <code>&lt;html&gt;</code>, and removed it at the beginning with JS. If the <code>no_js</code> has not been removed, that means the user does not have JS enabled. An additional CSS file was created to handle the styling for the 1%. </p>

<p>Update 2:</p>

<p>Much work has been done in the way of finishing the front end. I have pretty much finished the home page and am now wrapping up the "Projects" tab. </p>

<p>The vision I have for this website is that it will be clean and lightweight. The aesthetics will rely heavily on minimalism, but it should be unique and pleasing to the eye. Additionally, it should be reminiscent of a real world portfolio. </p>

<p>A picture is worth a thousand words, so I decided that the projects tab will be styled like a gallery where there will be representative pictures of each project. When the user hovers over the picture, a title will come up or perhaps a short description. The immediate problem with this is that mobile users won't be able to hover over the pictures, so a title will have to be displayed on top of the pictures. The next design choice is how to layout the pictures. Since I don't want to be tied down with uploading pictures of specific orientation or aspect ratio, the best solution is to use a masonry style layout. The downside to this is that it requires Javascript. Going with progressive enhancement, I am going to first lay out containers in a fixed rectangular grid with pre-specified aspect ratio, then fit the pictures to said containers. It isn't as pretty as the masonry layout but should get the job done for non-js users. </p>]]></content:encoded></item></channel></rss>