20140915

Sandwich Mechanics: Four Spreads and a Book

My sandwich-loving friends, I have been remiss. I've been tardy. I've been absent. I've been negligent, distant, and unattentive. I looked it up; it's been closing on two years since my last sandwich blog. What is going on, guys? [Just for] today, that all changes. Let's talk about sandwiches again, like the good old days.

Five. Five is the number today. No, I'm not going to tell you about five different sandwiches. That would be ridiculous. I have four spreads and a bonus item to tell you about, and oh have I been holding onto these in my heart for a while. Pretty much since the end of April. That's four and a half months, which is like ninety five years in sandwich time.

I received all of these items for my birthday from my dear sister, who clearly knows me very well and cares for me deeply. "Sandwich stuff," she thought. "I think he likes sandwich stuff." Understatement of the year, right? Now, I don't want to belittle her part in all this, but IT'S TIME TO TALK ABOUT SOME FRIGGEN SANDWICH STUFF.

Pesto, round two

Let's take it back old school (when your last blog post was almost two years ago, everything is considered old school, ya dork), to that time I was putting pesto on my sandwiches. Pretty cool idea, right? Yeah, my sister must have been reading my blog, because she sent me this sweet tube of pesto to try.

Wait up, hold the phone. "Tube"? Yeah, this Amore Pesto Paste comes in basically a metal toothpase tube. That's weird. It is accompanied by the usual problems associated with tube-delivered substances, primarily that as you get to the end of the tube, it gets harder and harder to get the stuff out.

The other weird problem I noticed is the consistency is a little watery, overall. The pesto is mixed with what appears to be olive oil. That's fine... you're not breaking any rules by using olive oil. But either it didn't mix properly in that tube or they put too much, because every time I squirted it out onto the sandwich, it was a bit disconcertingly watery. I do not see "sandwiches" mentioned as suggested items on the back of the tube, so I may have co-opted it for my own purposes.

In fact, that might have been enough to turn me off of it until I noticed how amazing it tasted. Just like the pesto before, the savory flavory worked so well with the other usual sandwich components. I know it's a really great sandwich when I pause mid-bite at the table where we're eating lunch at work, look real hard at the sandwich and say aloud, "GOD that's a good sandwich." I'm not even exaggerating.

So the pesto tube is down to the point of diminishing returns by now, and next time I think I'll go for the Trader Joe stuff instead, on account of better consistency, but thank you, weird metal pesto tube, for we had some fine sandwich times together.

Rooster Mayo

What do you guys think about Sriracha? I don't think I know anyone who likes spicy food but doesn't like it. My tongue--and by extension, I--was first exposed to Sriracha probably back in the summer of aught four, when I was also exposed to pho for the first time. My first thought was that it had a bit of a meaty taste, and we became fast friends.

But what do you think about Sriracha for sandwiches? My opinion, albeit without having tried it? It would be a bit overpowering. They must have been thinking the same thing, so they invented Sriracha mayo. It's a creamier version of Sriracha more suitable in consistency for a spread on a sandwich.

The fun ends with the consistency, though. The Sriracha mayo, while spicy, lacks enough of the great flavor we've come to expect from the exceptional sauce, that age-old problem with sauces that are too spicy but not spiced enough. I used it a few times, but sadly, it has fallen into disuse.

Cran Sand

The Cranberry Honey Mustard I received wouldn't be the first time I've dabbled in cranberry things on my sandwich. In fact, it wouldn't even be the first time I've dabbled cranberry honey mustard itself on a sandwich. So when I opened this one up and spread it on the bread, something reached into the deep recesses of my memories and told me it's gonna be a wild ride.

This one is not a honey mustard, just a Cranberry Mustard. Not surprisingly, it's much, much different than the stuff I had last time. It's thick, really thick, almost the consistency of honey itself. Spreading it evenly was an exercise in not breaking the bread. That's not a deal-breaker, though. Many good sauces are pretty thick. You just have to be careful how much you put.

The taste is also a lot different than before. It's sharp, really sharp, much more mustard than cran. In fact, the cran didn't shine through too much, which is a bummer for me. Though I've started acquiring a taste for mustard, I'm still on the pedestrian side; I won't go hardcore horseradish or super spicy. It was sharp, man. Frankly, I didn't like it a lot.

I tried it on a few things, just to be sure, including the bacon, egg, and cheese breakfast sandwiches we sometimes make. Maybe that was a poor choice, because it clashed pretty badly. Oops.

Red Orange Marmalade

I had no idea when I opened my birthday package that it would contain a spread that would change my life. This next one is so good that every other spread in the world is diminished slightly by its very existence.

It's Red Orange Marmalade.

You might be thinking, that's a bit of a funny name, right? You don't normally associate oranges with marmalade... in fact what makes something a marmalade, anyway? It sounds like conventionally, it's a jam with visible pieces of fruit. Honestly, I question calling this red orange marmalade a real "marmalade". It's just a sort of preserves in a unique sauce.

It's easy for me to like this, because I love oranges. I put them on or in pretty much anything I can get away with, of course including sandwiches. This spread is even more special, though. The oranges, of course peeled, are sliced thin and stewed in some kind of slightly sweet, thick sauce (apparently the sauce is black treacle and balsamic vinegar--NICE), so their usual sharpness is beautifully offset by the sweetness. The way this taste manifests in a sandwich, mixed in among all the other components, is truly wonderful to behold.

This spread is so good I'm now on my second bottle and about to buy my third, even though it's kinda expensive. Some things are worth paying a few bucks more for.

Now, in the picture I have it straight on the bread, but I found I like it even more if I do a thin spread of mayo on the bread, then the marmalade on top of it, to keep it from soaking a bit. I do this for just one half of the sandwich. The other slice of bread gets a heavier spread of mayo. I tend to put the cheddar on the marmalade side, too, because the bottle says "pairs nicely with a finely aged cheddar." Now, I doubt my medium or sharp cheddar from the grocery store is "finely aged", but it does go nicely anyway.

The only complaint, if I absolutely must, is that it's a bit of a pain to spread. It's very sticky and is mostly made of actual orange, not preserves/gelatin, so it comes out in a clump and I spend the next minute separating out the clump into individual bits of orange to arrange evenly around the bread. Still, if that's the most of my problems, then I am in great shape.

Wait, have I been typing orange this whole time? I meant onion... oops. That's what happens when you talk about marmalade, I guess.

The Compendium of Sandwiches

I did mention a book, didn't I? Yes, there is a book involved. A book came along with these delicious toppings. It is basically an encyclopaedia of sandwiches from around the world. That's the most amazing thing, by the way. I knew, as soon as I saw that it had Vietnamese banh mi in there, that it's a great book.

It's not the sort of thing you read cover-to-cover, but I do like to open to a random page and see what's going on. I may eventually experiment with randomly making some of the sandwiches found within, but I'll have to be selective, of course. Maybe I'll try a Jucy Lucy, which to my eye looks like a cheesburger.

Since it's got a pretty comprehensive list, you get the good and the mediocre all together. Some of those sandwiches are truly uninspired, I'm sorry to say. I mean, I think I can figure out how to make a plain ham sandwich, thanks.

How about we stick to talking about the great ones, huh? Speaking of great ones, my birthday and subsequent 5 months have been awesome, thanks to my sister, and, most importantly, sandwiches.

20140603

Developing LavaMite

The other day I finally published LavaMite, which is now happily posting to Twitter. That blog post was long, like almost 3000 words. I have at least as much more I can say about various things I encountered while developing it, so that's what this post is for. This one is all about nerdy coding stuff, you have been forewarned!

Firstly, though, I should also say that I published the source code and a downloadable package, plus instructions. Woah!

Start and stop without missing a beat

Oddly enough, one feature that took me a while code up was the ability to quit the program at any time and restart it from the point it left off. This was useful for restarting the program with any bug fixes or tuning updates. It required persisting the start time and other parameters of the last-executing round and reloading it on program start.

//
// if we're missing any of the information to calculate the correct
// offset into the last round, we put ourselves after the end of the last
// round
//
if (!haveAllLastActionTimeInfo)
{
    lastActionTime = rs.wholeRoundInterval.end + dur!"seconds"(1);
}

//
// this is really important. shift the round that we loaded from file
// to be offset from the current time. We calculate how far we made it
// into the last round, then adjust the startTime of the round to
// position the current time at that point.
//
r = new Round(
        rs.number,
        g_clock.currTime - (lastActionTime - rs.startTime),
        rs.startTime,
        rs.priorCooldownTime,
        rs.warmUpTime,
        rs.timeToStabilization,
        rs.cooldownTime);

setCurrentRound(r);

The program then has to skip whatever phases of the round (warmup, stabilization, or cooldown) that were already passed before the quit and pick up in the right phase.

//
// wait for a while to warm up the lamp partway, but not so much
// that it goes into "steady state" (with bubbles continually
// rising and falling). the whole point of this program is to
// capture the formations before it's stabilized
//
if (g_currentRound.warmUpInterval.contains(g_clock.currTime))
{
    //
    // when continuing a round, determine how far into the round
    // it is now. calculate the time remaining in this phase of
    // the round and only wait for that long.
    //
    // for new rounds, this will be the whole time for the phase,
    // since the time is currently just after the start of the
    // phase.
    //
    // add 5 sec to the time we wait, which will comfortably put
    // us into the next phase, once this phase is completed
    //
    Duration remainingWarmUpTime = g_currentRound.warmUpInterval.end - g_clock.currTime + dur!"seconds"(5);
    log(format("Leaving on for %s", stripFracSeconds(remainingWarmUpTime)));
    if (sleepWithExitCheck(remainingWarmUpTime))
    {
        break;
    }

    //
    // with the lamp warmed up as much as we want, take the money
    // shot and post it for the world to see
    //
    takeAndPostPhoto(camera);
}

By itself, it's not really that big a deal, except doing time math makes my head hurt. D has really nice classes like core.time.Duration, std.datetime.Interval, and std.datetime.SysTime that make this math readable and simple to do.

So why did it take me so long to implement? Making it testable took a lot more effort.

Becoming a Time Lord

Say I want to test that the program picks up properly where it left off. There are three phases of a round (warmup, stabilization, and cooldown), so at a minimum I need three test cases, each one quitting during one of the phases. I expect the program to resume and continue from the correct point in that phase.

Now consider that each phase might last over an hour. I can't wait 3 hours to get into cooldown phase to quit. As a programmer and human being, I definitely don't have the patience for that. I need a way to skip over all that dead time and get to the interesting stuff.

I went through at least three implementations of faking out the time until arriving at the version that worked. I can't even describe those older versions very well, because they were kind of convoluted and confusing. I don't think it's worth it. Let me say the salient features of the final version, which I think is not bad.

A clockmaker. No, a time-maker

The most important feature of the final, testable version of the dry run in the program involves a synthetic clock. For most things normally, I would Clock.currTime, but with the synthetic clock, I don't always want to fetch the real current time. I might want to fetch the fake time that the program thinks it is.

What sort of things would cause the real time and the fake time to differ? In a word, sleeping. Whenever the program sleeps, especially if it's a long sleep, I want very little real time to advance but the whole time requested by the program to pass.

Let's see what that would look like.

bool sleepWithExitCheck(Duration d)
{
    assert(!d.isNegative());

    Duration fakeSleepDuration = d;

    if (!g_forReals)
    {
        d = dur!"seconds"(5);
    }

    bool didReceive = receiveTimeout(d, (bool dummy) { });

    if (didReceive)
    {
        fakeSleepDuration /= 2;
    }

    g_clock.advance(fakeSleepDuration);

    return didReceive;
}

All sleeps, be they long or short, are truncated to 5 seconds, but the fake clock, g_clock is advanced by the original amount requested. g_clock is set to the true time at program startup, and calls to g_clock.currTime return the synthetic time in dry mode.

But these are not mere sleeps, rather waiting for the user-has-typed-Quit thread to tell us if the user wants to exit the program. The assumption here is that if the user did type quit, they most likely did it sometime during the requested interval, so we just guess that they asked halfway through. This fulfills an important requirement that the sleep duration was exited sometime before its end.

It's not great to have everything sleeping for 5 seconds, but it seems to work well enough. Ideally, short sleeps would sleep for less than long sleeps, but long sleeps would still not sleep for a boring amount.

Need to COMmunicate in serial

The PC part of the program talks over the COM port to the microcontroller and tells it when to turn on and off. I already had an idea off the top of my head of how to talk to something that's connected to a COM port in Windows. Whatever its failings, CreateFile does let you simply open devices like COM ports. Then you can use ReadFile and WriteFile to communicate over them.

Time to dip into the wonderful world of D interoperability with C. Actually, this is a core design goal of D, so it was really easy.

First, however, I needed to find wrappers for basic Windows types. These exist in the core.sys.windows.windows module, but I don't know where anything tells you that. I think I kind of stumbled upon it by accident. Once I imported this, I was free to define my own wrappers with impunity.

Though the module I just mentioned has a lot of things from kernel32.dll, it doesn't have everything, namely the COM port functions. I knew that I'd need to set the baud rate, parity bits, and so on. The Windows API to do that is SetCommState, with a few others. Here is an example wrapper.

struct DCB {
  DWORD DCBlength;
  DWORD BaudRate;
  /*
  DWORD fBinary  :1;
  DWORD fParity  :1;
  DWORD fOutxCtsFlow  :1;
  DWORD fOutxDsrFlow  :1;
  DWORD fDtrControl  :2;
  DWORD fDsrSensitivity  :1;
  DWORD fTXContinueOnXoff  :1;
  DWORD fOutX  :1;
  DWORD fInX  :1;
  DWORD fErrorChar  :1;
  DWORD fNull  :1;
  DWORD fRtsControl  :2;
  DWORD fAbortOnError  :1;
  DWORD fDummy2  :17;
  */
  DWORD fStuff;
  WORD  wReserved;
  WORD  XonLim;
  WORD  XoffLim;
  BYTE  ByteSize;
  BYTE  Parity;
  BYTE  StopBits;
  char  XonChar;
  char  XoffChar;
  char  ErrorChar;
  char  EofChar;
  char  EvtChar;
  WORD  wReserved1;
};

extern(C)
BOOL SetCommState(
  HANDLE hFile,
  DCB* lpDCB
);

Notice all the bit-field members of DCB that are commented out and replaced by a single DWORD, because D doesn't support bit fields in C structs. Anyone who wants to touch those bits will have to access them with some bitwise arithmetic--or I could have written member function wrappers for them. I didn't need to, myself, so I didn't bother. Tee hee.

In the context of Arduino I was able to find some sample code to make sure I was calling these functions right, too, which was handy.

private void setCOMPortParameters()
{
    DCB dcb;
    if (!GetCommState(m_hCOMPort, &dcb))
    {
        throw new Exception(format("failed GetCommState: %d", GetLastError()));
    }

    //log(format("Previous baud: %d, byteSize: %d, parity: %d, stopbits: %d", dcb.m_BaudRate, dcb.ByteSize, dcb.Parity, dcb.StopBits));

    dcb.BaudRate = m_baudRate;    // set the baud rate
    dcb.ByteSize = 8;             // data size, xmit, and rcv
    dcb.Parity = NOPARITY;        // no parity bit
    dcb.StopBits = ONESTOPBIT;    // one stop bit

    if (!SetCommState(m_hCOMPort, &dcb))
    {
        throw new Exception(format("failed SetCommState: %d", GetLastError()));
    }
}

Click click click click

Due to the way the relay is set up, it is "live" by default. The microcontroller's first job is to turn it off at startup. This produces an audible click, because the relay is mechanical inside.

So when does the microcontroller turn on? It turns out, a lot. When the USB cable is plugged in, it of course turns on, because it just received power. It also resets, apparently by design, whenever serial communication is initiated. You can work around it by soldering a capacitor, but I didn't bother reading any further because they said capacitor.

Actually, every time you open the serial port for communications, it resets several times, so when my program starts, you hear several weird clicks. It's unnerving but otherwise harmless, I think.

To compound this problem, my initial protocol for talking to the microcontroller used the strings "0" and "1" instead of the nice strings "switch_1" and "switch_0". I am almost certain that during the initial COM handshake or whatever the system does, it throws a 1 or 0 out there (the character value of '0', I mean). Once I changed it to the longer string it wasn't as bad.

My program only opens the COM port once (i.e. calls CreateFile on it) at startup, so the multiple resets aren't a major problem during the main loop of the program.

Don't talk so fast

I did my initial testing on my old laptop (which I'm using to write this blog right now), even portions on the bus. It cannot be understated how unwieldy it is to have a microcontroller and cables all over the place on the bus. If the other riders didn't think I was a weirdo before...

Anyway, it all tested nicely on here, but when I plugged it into my PC I had all kinds of trouble reliably controlling the power. Sometimes it wouldn't turn on. Other times it wouldn't turn off. It seemed like it just wasn't hearing the commands I was sending, even though the Arduino serial monitor tool worked fine, and I checked my COM port configuration settings thoroughly and reinstalled the FTDI drivers, to no avail.

I don't remember how I arrived at it, but I fixed this problem by putting a delay between opening the COM port for writing and actually sending the first command. I think my PC, which is beastly fast, was trying to talk to the Arduino well before it was actually ready, but my slow laptop just took longer to get to that point.

Looking ahead

I have two ideas left for this program, though only one I will probably get around to. I'd like to look at more interesting patterns for warmup. Right now it is a fixed time that the lamp just stays on. What if it pulsed on and off with a 1 min / 1 min duty cycle or something? I have so much of the infrastructure ready to go that it'd be a shame not to explore this a bit more.

My thinking is that I will determine the total warm-up time at the start of the round like I do today, and then turn the lamp on and off a random number of times with random durations of "on", to total that amount of time spent powered.

The only hiccup is my feature of resuming in the middle of the round, but I think I can solve this by persisting the number of active periods remaining in the round, and the current state of the lamp.

My other idea is to use some kind of image processing to choose the picture to tweet, instead of a random time like I do today. I already have the camera taking pictures every 1 minute. When it gets to the cooldown phase, it has a whole set of pictures from the round, and some image processing could look at them all and pick a "good one" based on some heuristics. This could get arbitrarily complex, and it's in a whole new field of computer science, so I'm going to put it off for now.

20140529

LavaMite: It's Out Now

It was some time last year, back in good ol' 2013, when my wife bought herself a lava lamp from Amazon (what don't we buy from Amazon these days?). I said, "What's this? No, I know it's a lava lamp. Why do we have it?" She said, "'Cause it's cool." "Whatever, dude." I had a lava lamp as a kid, and I didn't recall anything particularly interesting about it.

But a few days later she'd had it on for a while when I came home from work, and it looked kinda, hm, funny. You know how lava lamps are normally depicted: globs of whatever (wax) bubbling up and down languidly. At that point it looked more like a cave formation, some jagged sculpture randomly built up from the ground from aeons of mineral collection. "Huh," I said, "interesting."

After chancing upon her lava lamp in a similar state a few times, I mused idly aloud that I bet I could make a program to catch the lava lamp "in the act" of looking more interesting than they generally do. That got the wheels in my brain turning. A few months later, LavaMite is born (update: source code, download, and instructions now available). The name is a dubious portmanteau of "lava lamp" and "stalagmite", which should surprise absolutely nobody who knows me.

I like this project because it is basically my very first endeavor that you could venture to call artistic. Not that there's some grand or deep message I'm trying to convey; I just saw something unusual that people probably overlook, and I wanted to share it. Best of all, I think it has turned out successfully--the images it captures fit my original vision. My technology has realized my intentions in a way that most of my other projects don't (usually from abandonment).

So now you know why it is. Read on to find out, in probably progressively gorier detail, what comprises it and how it works.

Several moving parts

With a goal in mind, I needed to come up with a system to capture the images of my (or my program's) choosing. First of all, I'm going to need a lava lamp. No problem, I'll just steal my wife's aforementioned lamp (hearing angry yells about stealing her stuff right about now). Secondly, I'll need something to turn it on and off. Hmm, some kind of computer-controlled power switch. We'll get to that shortly. Thirdly, I need to snap a photo of the lamp. That will require a webcam (already got one) and software to take pictures. Fourthly, I need software to share the picture online. Let's tackle these one at a time.

Oh, one last restriction. I sometimes use new projects to learn a new progamming language, since I can't really learn a new language well without applying it to a real problem. I used this project as a vehicle to learn D, a language which my friend @neworb couldn't shut up about. I have a bunch of thoughts on this language, which I will probably save for a different post.

The power to power and un-power

I did some research about what I might use to turn the power to the lamp on and off. I've seen those timed power switches before, with the clock-like dial where you set on and off periods, but I want to dynamically control when it goes on and off, so it needs to have a computer interface. I looked up network-controlled power switches. Holy cow, these are expensive. I didn't want to spend upwards of $50 (and generally much more) to make this thing.

Well, I've got the old Arduino Duemilanove sitting in the closet, collecting dust after my microcontrollers course a few years back. Maybe I can put that to good use. I remembered that it has a USB/serial interface, so it would be easy for me to control from a PC. It has several pins that I can turn on and off programmatically. I just need a power switch that activates or deactivates based on something like a 5-volt / 0-volt signal.

Quick preface to the next part: I know practically nothing about circuits. I'm a CS guy, not an electrical engineer, and when you show me a circuit diagram, my eyes glaze over. All the circuits related technology I ended up using in this project--admittedly, a laughably small amount--was nonetheless stretching my skills. BUT! I didn't kill myself with a live wire, so that's good, right?

I did some searches for Arduino-controlled power switches. I found a bunch of circuit diagrams and warnings about "live rails" and killing yourself with amps. I got a bit worried, so stepped back a bit. Maybe I could find something a bit safer? I came upon a nice looking device called the PowerSwitch Tail II. It looked perfect: for $25 I could get a power switch specifically designed to be controlled by Arduino. I nearly bought the thing. I don't know why I didn't, honestly.

Something made me go back and search for "relays" on Amazon, and I turned up this little SainSmart 2-channel relay. From looking at the comments and reviews I was able to glean that this $10 gadget might be exactly what I was looking for. Even better, it's a fairly popular part, so I found a wealth of information on YouTube about it--great tutorials and so on. This is what I ended up buying, and I'll say more about the actual exercise of putting the solution together in a bit.

My very own personal photographer

I already had webcams lying around, so I just grabbed any old one, in this case a Microsoft LifeCam VX-5000, I think. That's the easy part. The harder part was figuring out how to interface with the Windows camera APIs to take a picture using it. Heck, I don't even know which API to use for this. Apparently in the olden days you would use WIA, but it has since been deprecated in favor of MediaFoundation.

I found this very good CaptureEngine sample that does more than I needed, such as record videos from the webcam to file (cool!). To be honest, I didn't really follow most of this code--it's all MF gobbledygook about frames and sinks and media types, but I got enough to figure out how to snap a single picture.

It wasn't so simple, though, as it rarely is. Have you ever used a webcam and noticed that the video stream adjusts to the lighting conditions after turning it on for a few seconds? The colors in the picture seem much better after it's stabilized, right? The code I hacked in to take a photo didn't do any of this stabilization at first, so I had to pull in the code to start a preview, leave it on for a few seconds, and only then snap the picture. It wasn't a big deal, but it's worth mentioning.

I implemented this functionality in a C++ executable, separate from the main program, because MediaFoundation is a Windows COM interface, which I could not get to interoperate with D easily. I think it might be possible if I create a ton of wrappers, but that's basically the least appealing thing, so I just took a simpler path. I could have made it as a C++ library and wrapped a simple interface for the main D program, but it just didn't seem worth it. Plus, command line executables are really easy for testing with along the way.

A little birdie to share photos

The final sub-component is something to upload a photo to Twitter, the sharing medium I decided on. Twitter is a good choice, because there are a lot of libraries already out there for integrating with it. In actuality, a huge part of the decision to use Twitter is probably the works of Darius Kazemi, whom I went to highschool with, and who is now an Internet bot-maker phenomenon of some kind. I guarantee that, before seeing his stuff, I did not think of Twitter bots as a medium of expression.

I found a Twitter library for D called graphite. Grabbing this library required me to learn about dub, the package manager for D. There was some learning curve involved, because the documentation for it is kind of spotty. When I got compiler or linker errors with a dub build but not with a regular dmd build (using the D compiler directly), it was more of a pain to figure out the cause.

Actually, I had a lot of problems getting graphite to work. The very first time I tried to load it, I got syntax errors, like something was fundamentally busted in it. I looked at the source and could not for the life of me figure out how it could ever work. I kept stripping out more and more pieces of it until the barest essentials kind of worked.

As soon as I added back HMAC functionality, a crucial part of Twitter authentication, I started getting real crashes, as in postmortem debugger, not just D exceptions. This ended up being a bug in the D runtime, and having to recompile D from scratch was odious enough to put me off of this project for literally months. Battling my tools is one thing that tries my patience more than almost anything else in software development, let me tell you.

When I came back after my couple months away, I reinstalled some stuff, re-downloaded graphite, used the recompiled D toolset and runtime, and everything magically worked. I have no idea what to thank, but I don't care about this aspect enough to question a battle won.

The best part about graphite is it really does take care of Twitter functionality for me. Doing OAuth by hand is kind of a pain, for some of the same reasons as other security-related stuff: by design, it is hard to debug, lest an attacker gain any purchase.

Check out the entirety of my code that interfaces with Twitter. This is kind of awesome.

void tweetTextAndPhoto(string textToTweet, string photoPath)
{
    string[string] parms;
    parms["status"] = textToTweet;

    log(format("Tweeting \"%s\" with image %s", textToTweet, photoPath));
    Twitter.statuses.updateWithMedia(g_twitterInfo.accessToken, [photoPath], parms);
}

Programming the microcontroller

It's pretty cool how popular Arduino microcontrollers have become in the last several years, because it means there is a wealth of information out there on how to use them. Even better, the toolset is supported pretty well on Windows (where I do all my development), a sort of rarity among open source projects.

The code is about a hundred lines long, and half of that is comments. The microcontroller reads the serial input line (which is transported over USB) until it receives the string "switch_1" or "switch_0", upon which it will turn on or off the voltage on one of its digital I/O pins. I just happen to connect this pin to the relay, so I can provide or cut wall power to the lamp.

void loop()
{
    int foundString = -1;
    const char* strings[] = { "switch_1\0", "switch_0\0", NULL };

    foundString = waitForString(strings);
    switch (foundString)
    {
        case 0:
        digitalWrite(switchingPin, POWER_ON);
        break;

        case 1:
        digitalWrite(switchingPin, POWER_OFF);
        break;
    }
}

Wiring it up

Probably the hardest part of the project was doing the actual circuit wiring, even if there was an embarrassingly small amount of it needed. Luckily, the parts I chose were popular enough that I could find really good YouTube videos of similar projects, from which I could extrapolate what to do in mine. Constantly lurking in the back of my mind was the threat of shocking myself really pretty badly, but I'll forestall your worry right now: I got through unscathed.

I wanted to see the relay itself in action first, without any live power involved. I ordered a little pack of adorable multicolored wires and set to work dutifully connecting up the pins I cared about to the relay, leaving the actual power cable out of the picture for now. The relay has a handy LED on it that lights up when the circuit is closed, so I could know if I'm successfully controlling it.

Having hooked everything up and loaded my simple program on the microcontroller, I used the serial input window of the Arduino tools and (programmatically) threw the switch! ... and nothing happened. Suddenly, like the weight of a freight train, I was hit with the realization that I was reduced to the same status of most of the people whose computers I help troubleshoot: "I flipped the switch, and it didn't work." "What do you mean, it didn't work?" "I dunno. It didn't turn on." I had not even the vocabulary to express the thing that wasn't working. It was refreshing, eye-opening, and, frankly, pretty annoying.

I didn't realize this at the time, but I think the digital pin I had chosen happened to be reserved for additional serial communications, so it was never going to work. I switched to using pin 13, which is also wired to an LED on the Arduino board. I could see this LED turning on and off correctly, so something was working.

I broke out the multimeter and checked both ends of the cable (painstakingly, with a head-mounted lamp strapped to me, and in a cramped sitting position). Hey, if the voltage is high at this end of the cable, shouldn't it also be high at the other end? I swapped the adorable, apparently cheap cable, and things sprung into action. I heard that click from the relay I was waiting for.

Speaking of click, I didn't know how a relay worked before this, but it's super cool. Did you know there is a physical switch inside? A small piece of metal is pushed away from or pulled towards a metal contact by an electromagnet. How cool is that? (if you ignore the inevitable mechanical failure)

I wasn't about to do my first live test using my beloved lamp. I took an old phone charger and cut the cable. The charger had its own power adapter, which I think reduces the current and voltage on the actual wire, for safety. As instructed by the tutorial video, I spliced the live ends together and put the two parts of the neutral line into the terminals of the relay. With every click of the relay, I could see the phone start and stop charging. Nice!

The test having succeeded, I chose a standard extension cable as the real accomplice for my relay. One nice thing with the extension cable is that the positive and neutral lines are individually shielded in plastic, so I never even exposed the positive wire, further minimizing the chance of shorting.

OK, but what about the actual program?

So far all I've done is describe the individual parts. The actual program, written in D, has to put them together in a meaningful way. I knew what the main loop of the program should be right from the start: turn on the lamp for a while; snap a picture and tweet it; keep the lamp on long enough to start bubbling normally (I don't want it to cool in formation); turn off the lamp for long enough to "reset" it.

Each of these parts has some nuances to them. The biggest question is how long each of these phases should go for. Warm up for too little time, and all you see is a blob on the bottom. Warm up for too much time and you see only a normal, bubbling lava lamp. Leaving the lamp on too long in general (like, 10 hours) is not good for it, I think. Cool down for too little time, and the next time you warm up, it will skip over the "weird stalagmite" phase and straight to bubbling normally.

From observing the lamp out of the corner of my eye for weeks or months before finishing the project, I knew all these things would need adjusting, so I built in features to allow me to tune the timing right away. In addition to the "money shot" that gets uploaded to Twitter, the program keeps a running thread in the background that takes a photo every 1 minute and just keeps it on disk. Later on, I can look at the times chosen in an unsatisfactory round (one in which I don't like the picture that was posted) and see with my eyes the time range in which the interesting structures presented.

Scrolling through the images real fast also makes for a pretty cool time lapse video.

I used a spreadsheet to keep track of the prior cooldown time, warmup time, and visually-inspected "interesting range" of times for each round. From this I was able to extrapolate a range of warm-up durations and cooldown times that would produce interesting formations. The program simply picks a random time to wait within that range, before taking the picture. In case you're curious, if the lamp cools for 4 hours or more, it is usually looking interesting in the 90 - 120 minute range after turning it on again.

That's actually it for the simple stuff. I still need to publish the source code. I also have a lot more to write about, but it's in other weird details, programming decisions, and hurdles I overcame while creating this. I will certainly write about these in further blog posts, but for now, enjoy the weird lava lamp pictures that come from the machinations of LavaMite!

20140327

The Trip to Taiwan Was a Treat

Pardon the title. I just couldn't help it. Back in February I was able to go on a business trip to Hsinchu, Taiwan, for work. Time zones and travel time are weird, so I have trouble understanding just how long I really spent there, but it went something like this.

I left Seattle on a Saturday and arrived in Taiwan 14 hours later, via a practically nonexistent layover in Narita, on Sunday very late at night. We had Monday to ourselves to sightsee--I mean, acclimate. Then followed two days of, ahem, grueling meetings, and we flew out that Thursday afternoon, only to arrive back in Seattle, um, that Thursday morning.

I'll say it again: timezones are funny things. Taiwan is 15 hours ahead of west coast USA, where I live, so I was routinely calling my wife on the subsequent day, and she felt like she had to wait "longer" for me to finally get home.

We accomplished a lot on the trip, but it was not without its enjoyable moments, which I will go on about for a while here, mixed with some other thoughts about Taiwan in general from the admittedly limited glimpses I got.


My boss and one of my coworkers standing just outside the Taoyuan airport. Who could ask for finer traveling companions?

It was probably 10 PM at least when we got into the cab for the roughly 1 hour drive from the airport to Hsinchu, where we were staying. By the time we got there, very little was open for food. After passing by a dubious looking "Moss Burger" and McDonalds, we wandered into an absurdly garish diner called the "Happy X-Mas Cafe" or something like that, despite it being February and not December. The food there was not really to my liking, but I was hungry, so what to do?

I was especially lucky on my trip to have slept like an absolute rock every night. I think jetlag had a strong hand in that, too. It was a very nice Sheraton with a big, spacious room and a comfy bed. Lucky!


The view from my boss's room the following morning. The window washers hadn't been by my room yet and the windows were filthy.

Check out the fancy, shiny lobby at the Sheraton.

They had an extensive hotel breakfast every morning, with items ranging from the mundane (cereal) to the mildly adventurous (stewed apples of some kind) to the exotic (grilled fish jaw!?) to downright alien foods that I couldn't even identify as animal, vegetable, or mineral.


Shiny fancy elevator. Look, a cameo of me!

Signage inside an elevator we rode. I am interested in the third panel especially.

The driving there was far more tame than, say, India or Turkey. In a pinch I think I could have driven, but the drivers still seem to have that sixth sense about nearby drivers and scooters that prevents them from running into each other constantly. We just took taxis wherever we needed to go, pretty much.


Scooters are a big deal in Taiwan, so much so that there are dedicated markings for them at stop lights. All the scooters line up in a little white box in front of car traffic and get to go first when the light turns green.

More photographic proof about scooters being a big deal there.

We took the high-speed rail (HSR) from Hsinchu to Taipei. It looked like the usual means of commute for a lot of people who don't want to live in the big city. True to its name, the train runs almost 200 MPH, so it is kind of exhilirating to look out the window and see everything going by unsettlingly quickly.


On the way to the train station.

Signage: I guess crocs are popular enough that they have to warn everyone not to get stuck?

The Hsinchu skyline, I guess. I don't think you can see our hotel in this shot. They really like to top their buildings with domes and other spires.

Check out these two shady guys waiting at the train station.

More signage. My favorite is the middle one: if you can't find your kid, he is probably hiding underneath the platform!

From the HSR we transferred to the Taipei Metro, which has a sprawling map of color-coded routes very much like the DC Metro. We bought a 1-day pass and had no problem going all over the place with it. Really convenient. Our first destination was the Taipei 101 building, which at one time was the tallest building in the world.


Inside a Taipei metro train car.

After getting off near the 101 building, they had all these little confectionaries and pastry shops in the train station. Kind of upscale-looking and very westernized.

Some strange robot/engine art on the walk to the 101 building.

The 101 building. It's pretty impressive, and, like most things of this sort, pictures don't do it justice.

We took the elevator up to the 80-somethingth floor of the 101 building where they had an observation deck. The elevator is touted as being very high speed. It accelerated quickly yet gently up to about the midpoint of the vertical journey and spent the remainder decelerating.


The view of Taipei from the top is impressive. They clearly favor high rises and skyscrapers, but still have some open areas in the city. We spotted a lot of recreational facilities--track and field arenas, tennis courts, etc..

The top of this skyscraper has a "super damper" (which is apparently its actual name) to help prevent lateral sway. Apparently it acts as a kind of weighted pendulum to counteract the sway of the building, and many especially tall skyscrapers have one.


The very large mass damper. Though there's no frame of reference for the scale here, but it is at least 20 feet in diameter.

Out front of the 101 building is this piece of modern art that is supposed to be a... face? a fetus? Who can say for sure?

We were ready for a little snack so we ate at a little place called... Ireland's Potato!? It is basically a kind of bizzar poutine shop: french fries topped with different sauces, meat, and so on. It was yummy, as such junk food tends to be.

My boss is a lover of horses, including this weird metal one.

We next took the metro trains to the Maokong Gondola, which was supposed to afford a view of the city from atop a mountain. Unfortunately, a lot of things are closed on Monday, and nobody told us! The gondola and the neighboring zoo were both closed.


Neat topiaries at the zoo.

Signage: don't climb all crazily over the escalator, man.

Look, it's a Starbucks... surprise, LOOK AGAIN.

Our final tourist stop for the day was the Shilin Night Market, a sort of public market where lots of vendors set up little stalls all selling the same kinds of street food, suspicious bootleg merchandise, and, uniquely, running carnival games. As far as I could tell, the night market's vendor population was divided pretty equally into those three parts. In terms of layout, it reminded me a little of the spice bazaar in Turkey, of course without the spices. It also reminded me of Paddy's Market in Australia


In this picture, I'm standing outside a small temple right in the middle of the night market, taking a picture of a bit of the market itself.

We got back sometime after 8, and headed out to a late dinner. Unfortunately, due to the everything-closed-on-Monday problem, the place we planned to go (and basically every other place) was also closed, so we were stranded with no prospect of food in sight. Suddenly out of nowhere, we chanced upon a place claiming to serve burgers, steaks, and so on. We couldn't really say no.

By all rights, this tiny restaurant simply should not have existed in Hsinchu, Taiwan. The decor inside smacked strongly of western influences, but everything was just slightly off. I ordered a bacon cheeseburger and received a delicious looking burger... lacking a burger patty. Just a pile of bacon on a bun with all the other fixings. So strange. (we asked for a burger patty and all was good)


Enjoying a plate of... onion rings!? They were good onion rings, too!

Such a strange mishmash of decorations to find in a place like this.

Coming back to the hotel, I slept the sleep of angels. Playtime was over, and the next two days were strictly business... or so I thought! Actually, the guys we were visiting hosted us very nicely. We went out to a great lunch at a place that primarily served deep fried, breaded pork cutlets, and they were every bit as delicious as you might imagine.

They also took us to a nice restaurant for dinner where they served what seemed much more like traditional Taiwanese home-cooked food, many simple but tasty dishes. I felt like I was eating in some grandmother's house, not a restaurant. The highlight of the recreational portion of the trip, they arranged for everyone in our traveling group (around 10 people) to get two hour Thai massages. Drifting in and out of a jetlag-fueled stupor, I nearly fell asleep repeatedly as the masseuse contorted my body unnaturally and pounded out all the knots. In the US, such a treat would run at least a hundred bucks, but there it was less than forty. Wild.

On the last day, we were taken out to one last meal to a yakiniku restaurant, which is a Japanese grill-at-your-table kind of place. They brought delicious Wagyu beef, shrimp, chicken, scallops, and it was all amazing... until I got food poisoned from it sometime in the middle of the night. The next day or however long was about as bad as you could expect, what with traveling and all, but there was a silver lining.


Amazing Wagyu beef. I'm pretty sure it was undercooked scallops and not this perfect specimen that turned my insides upon themselves for the following days.

Other colleagues from our traveling group enjoying our dinner and not getting food poisoned. Hmph.

For the first time in my life, I was able to travel on international business class on the long leg of the flight back (10 hours). It was so unlike any flying experience I've ever had that I have to say a few words about it.


Signage at the airport: don't bring your hacksaw, slingshot, nunchakus, or bow and arrow aboard, please.

The console in front of my seat on the plane. The button panel for adjusting my seat has more functions than most calculators. The "Push" button swings the screen out for a better angle.

Those are my feet and legs, stretched out as far as they'll go. On an airplane. And I hadn't even yet messed with the multifunction calculator--I mean, seat adjuster, to make myself lie 100 percent flat. That's pretty disgusting.

A/C outlets and a USB charging port right on my chair.

The stewards and stewardesses in the business section treat you like kings. They will bring you practically anything you ask for, but I felt awkward being catered to so closely, so I mostly just kept to myself. I didn't really partake in the amenities, opting instead to sleep in a state of uncertain stability for most of the flight. It would have been so much worse back in economy, let me tell you.


The tragedy of getting this delicious salad and broccoli cheddar soup on the plane is that I ate maybe five bites overall, over the course of half an hour, before I felt like it was inciting further digestive rebellion, and I had to stop. I didn't even ask for the dinner course later, but it smelled so good, even to my traitorous senses.

I got a taxi back home by about 10 AM, at which point I crawled into bed and slept from pure exhaustion. One day later and I was operating at 90% capacity, thank god. It was a good trip overall, but, as I've learned, I'm most likely to remember the striking return trip than any other part, so it's a good thing I wrote it all down, huh?