Bites to Bytes

A blog of Jade's creations and projects

About this blog: Sandstorm, HackerCMS, Cloudflare, Cloudflare Apps

By Jade Wang - 04 Mar 2018

This blog is hosted on Sandstorm using the “Hacker CMS” app and modified with Cloudflare Apps.

Hacker CMS is a simple CMS that Kenton wrote in a day as a demo of what can be done on Sandstorm, powered by Jekyll with an embedded Ace editor.

Fun fact: my blog server is only running while I’m editing, e.g., when I have the grain open on Sandstorm. But it stays up because it’s behind Cloudflare.

Also, because it’s behind Cloudflare, I can make modifications on the edge with Cloudflare Apps. Here are the Cloudflare Apps installed on this blog:

Additional modifications on this blog:

The great thing is, neither of those add-ons require the server to be up to work, similar to how the Cloudflare Apps also don’t require the server to be up. :)

All-in-all, I’d say I’m striking a reasonable balance between customizability and convenience. That is, it’s neither the most homebrewed DIY blog solution possible nor is it the most automated not-really-customizable consumer-edition.

Protein Muffins: gluten free, keto, buttery

By Jade Wang - 17 Feb 2018

This post was originally published on my other food blog and the recipe requested by friends and family for the past couple years.

Gluten free, high protein, and has the carb-y mouthfeel of a real bread dinner roll.

I feel like the vast majority of culinary innovation in human history has been about making carbohydrates taste like protein, yet there is so precious little in the way of making protein taste like carbohydrates. So I experimented around a bit and came up with this. (Variants of this also include pancakes, English muffins, etc.)



  1. Spray a muffin tin with cooking spray (or grease it with butter) and let rest in freezer. Preheat oven to 350 F.

  2. Mix dry ingredients together in one bowl. Mix wet ingredients together in separate bowl using a mixer.

  3. Slowly add dry ingredients to wet ingredients while mixing.

  4. Remove muffin tin from freezer (you’ll see a thin film of solid grease on its surface), and fill the wells 1/2 - 2/3 full.

  5. Bake for 12 - 15 min. or until golden brown (see photo). Timing may depend on the idiosyncracies of your oven.

  6. Let cool on cooling rack.

Homemade doorbell using Arduino, Twilio, Node.js, and a box of mints

By Jade Wang - 11 Feb 2018

The doorbell finally works! SMS-to-Pebble notification, and no delay on ding-dong audio.

Over my holiday staycation, I decided to start working on my long-delayed doorbell project. Backing up for a moment: I have a confession to make about tech debt. For many years, we have not had a functioning doorbell and relied on a well-documented workaround.

Faded post-it note reads: “Does not work; please knock.”

My husband Kenton has had the idea to make a smart doorbell since the construction of the house but simply got too busy to actually work on it. And continued to be too busy. For seven years. So I took matters into my own hands. (To be fair, some of those years include us co-founding a startup together and then starting our new work at Cloudflare. And he did start by implementing our home security system, and then ran out of free time.)

Note: this is my first Arduino project, and though I have a few small electronics projects under my belt, I do not by any means claim to be an expert.

How it works

Ingredients: Node.js, Arduino, Pebble (paired to Android phone), Twilio API, Audacity, Sugru, lead-free solder, a box of Whole Foods mints, hot glue gun, and a bunch of npm packages.

Circuit diagram scrawled on a post-it note with color labels to help me keep track.

That’s the short version, the pretty-straight-forward version. But the truth about building it and no-filter overly-honest-methods story with all the missteps along the way is a more fun story to tell. So here’s how the adventure started.

Doorbell: the making-of

The Original Spec

(as scrawled in dry-erase on a whiteboard.)

Order supplies

In preparation for having some stay-cation time, I order all my supplies early so I have all of my days off to work on the doorbell project. It shouldn’t take long, right? ;)

This is my very satisfying haul:

My holiday Adafruit haul (clockwise from top): mini-breadboard, alligator clips, rubber feet for Arduino, Arduino, jumper cables, resistors.

Make sure the button works

Actually, before making sure the button works, the first step is to figure out which wires in the server room correspond to the doorbell at the front door. Luckily, Kenton left most things reasonably well-labelled, so the only wire bundle left un-labelled should be the doorbell, but I still needed to use a multi-meter to check which wires in the bundle were actually hooked up to the doorbell.

There were 6 wires in a brown bundle coming out of the wall. Each pairwise connection appeared to have infinitely high resistance, except for one pair, which was negligibly low. That’s good. Lower than I was expecting (is the button stuck in the on position?), but pretty sure those are the relevant wires.

Six wires terminating in the server closet.

Next, I unclipped the doorbell from the wall by the front door, and unscrewed the wires holding it to the plate. Pressed it a few times. Feels like a good button, smooth action, and is not stuck in any way. That’s good. Here’s a diagram of how the doorbell should hook up.

Left: original circuit diagram for how the doorbell is hooked up. Right: after ripping out the bulb. “Computer” here means Arduino, server, and literally everything else. (Scribbles along the periphery: Factorio diagrams.)

Just to be thorough, I test the button with the multimeter to confirm the button does what I think it does. Nope. Fully pressed and not-pressed are both approximately the same as a piece of wire. Huh. Options at this point:

  1. Buy a new doorbell component.
  2. Disassemble this one and fix it.

My first choice was (1) so I shopped around on Amazon, but literally all the options were either ugly beige, full of cast-iron-looking frilly decorations (which don’t match the aesthetics of the house and would result in complaints from Kenton, who will definitely notice – in fact he rejected all plausible options for being too ugly), or part of a walled garden smart doorbell system which requires me to use some company’s proprietary app. So I walk to Fry’s and my luck there isn’t any better. But I impulse purchase some LED kits – well, not impulse purchase. I have another project I’m planning. More on that in a future post.

So I might as well take the doorbell apart as a puzzle if I’m planning to buy a new one anyway. So I disassemble it, and the connectivity of the metal parts are exactly what I’m expecting (see diagram above), and there’s a tiny incandescent bulb. Incandescent. Wow, when was the last time I saw one of these?

I measure the resistance across the switch (the two bendy metal parts the button applies pressure on) as I press the metal parts together. That part works fine. Infinite resistance to zero to infinite as I press and lift. Good. Let’s see what happens when I measure across the whole button circuit when pressing it. Doh. There’s no change when I press the button because it’s like it’s always pressed. It’s like the light bulb is a wire.

OH: I’m pretty sure burnt out bulbs are basically, like, insulators.

Let’s measure across the bulb and see. Oh hey, approximately zero ohms.

Me: Nope, I’m pretty sure this burnt out bulb doesn’t care what you think. It’s basically a wire.

Well, I guess I could just rip out this bulb and it would work. Do I really care if the doorbell lights up? Could someone find the button in the dark? Well, there’s other ways to fix that. I have glow-in-the-dark nail polish left over from Halloween. :D

So I rip out the bulb, paint the inside of the button with a few coats of glow-in-the-dark nail polish, let it dry overnight, and reassmbled the button in the morning. Fixed! Now the right side circuit diagram (from above) applies.

Sometimes, integrations just work, like snapping together Legos.

Now that I have a working button, I followed the Arduino Button Tutorial. Success, the button tells the LED to light up when pressed!

Next, I integrated the Twilio API (meteor add twilio-meteor), so each button press sends me a text message, which you can see on my Pebble.

Now to play a ding-dong sound. I learned by reading this ChromeCast-Arduino sketch that one can send an HTTP request to a Chromecast to play a sound. So the first step is to make sure my button presses can send an HTTP request, and I used RequestBin to test.

It’s hard to see, but in the beginning, the last request on RequestBin was from 15m ago, and after the refresh, the last request is from 12s ago.

And I was pretty sure I’d prefer to use the breadboard in my next project, so I sacrificed a couple jumper cables, soldered the 10 KΩ resistor to them as per the diagram, and put it in this mint box. Since I don’t have a heat gun, I used a hair dryer on the heat-shrink tubes.

I added some holes on the box to make room for the cables to come out, and used hot glue to make thise edges not sharp. I also hot glued a piece of plastic to the bottom of the tin so the arduino would (1) fit snugly and not jostle about and (2) not be sitting directly on the metal.

Useful things I’ve found in Kenton’s junk drawer: heat-shrink tubes, USB-B cables (a.k.a. “random old printer cables”), lead-free solder, a soldering-kit that I gave him as a birthday gift several years ago, wire-cutters, wire-strippers, various screwdrivers, and hot glue gun (I guess that’s from my random crap).

Decisions, decisions, decisions

Button de-bounce

During testing, sometimes I give the button a nice firm press in the center, and sometimes, I grab it by the edge and maybe it flutters a little on the way down. This is a problem because fluttering (the technical term is switch bounce) would result in me receiving anywhere between 2 and 10 SMS messages from a single button press. Oops.

There are a few options to consider on how to debounce:

Any of them would have worked fine, but I decided to implement the debounce in the Arduino sketch because I have an intuitive bias towards fixing the problem closer to the source. There is a ‘proper’ way to debounce in Arduino-land, and reasons not to implement my quick-and-dirty debounce (which is inserting a simple delay to all processes of half a second after each press), but I don’t intend to have other sensors or components attached to this particular Arduino for this project, so this doesn’t throw other components off.

Also, it was 2AM and I just wanted to fix this one bug before declaring victory and going to sleep.

Ditching Chromecast

In my first implementation, I sent an HTTP request to the Chromecast instructing it to play a YouTube video that had a ding-dong audio. This was inspired by this ChromeCast-Arduino sketch, so basically instead of ordering an Ethernet shield and using that sketch, I just wrote JavaScript to do the same things on the server. Well, it worked – you just have to wait a while to hear the ding-dong.

This resulted in a 12-second delay between button press and DING-DONG.

Of course, starting up the YouTube App in Chromecast might have something to do with it. So, the next implementation plays a ding-dong mp3 file which I edited heavily in Audacity so that it was loud enough and short enough.

This resulted in about a 5-second delay between button press and DING-DONG. Still too long.

Now I’m fresh out of ideas on how to shave off more seconds of latency, so I swivel around and ask Kenton for help, who suggests that I don’t use Chromecast, and play locally through speakers instead. Next steps:

  1. Order an amp on amazon and while waiting for it to arrive (this part takes a couple weeks, which paused the project until after staycation).
  2. Get the ding-dong to play locally through my laptop speakers (might as well get this part working while waiting for the amp to ship).

Part of step (2) is making the whole thing a plain Node.js app.

Plain Node.js vs Meteor

My first implementation was a Meteor app, using this meteor serialport package, because it was super easy and straightforward to use. However, using that particular package pinned me to an older version of Meteor. That was ok at first when I was playing audio via Chromecast and I just wanted to get something working quickly.

But after deciding to ditch Chromecast, I need to play audio via speakers, and as I found myself shopping around, all those npm audio packages required a newer version of Node. Embarrassingly, it took me a bit of time looking at dependencies, wondering if I could get away with just using older versions of the audio packages, before I realized that would be way more work than removing the Meteor layers so I could use the current version of Node. I’m so used to Meteor that this felt like venturing into uncharted waters. I’d hit Command+S and stare at Chrome like a chump, waiting for it to refresh by itself.

One evening of futzing around and one-more-bugfix-and-it’s-ready-to-deploy…

Fast forward to mid-January after the Amp arrives…

Hooking up the Amp

After a shipping delay, the amp finally arrived in mid-January, so when I found some free time, I hooked it up to the living room speakers.

Actually, I misread Kenton’s labels and first hooked them up to the speakers in the wrong room before fixing it. And made poor contacts the first time which resulted in a distorted, noisy ding-dong, rather like you’re hearing the ding-dong on a car radio that’s going through the mountains.

Since this was a very basic amp that accepted raw wires, I had to be careful with the amount of pressure I put onto the little pieces of plastic and springs that held it into place. There are plenty of things I’m good at. Not breaking tiny plastic components whilst clipping them into place is not one of them.

I actually did break one of the little buttons, which came loose from the spring, but was able to put it back together. Phew. o_O

Current status, and known issues

Currently, the doorbell functions as described in the how-it-works at the top. It successfully plays exactly one ding-dong every time the button is pressed and sends exactly one SMS message to each of our phones.

Arduino enclosed in mints box, connected to server via USB, and connected to doorbell via wires that go into the wall, with alligator clips extending the reach slightly. And the server is also connected to the amp via USB, which is connected to speaker wires that run through the walls. Next version will have a better wiring solution. But Garply (the cat) isn’t allowed in this part of the server room so it should be fine for now.

Great. Finally it works perfectly. So we keep the server running all the time now, right?

So we leave it running like we intend to, and eat dinner, watch a movie or two. A few hours later… DING-DONG. I run to the door, but there’s no one there. Huh. I test it, and it works as intended. Another few hours later… DING-DONG. And no one there. Maybe one of the alligator clips touched something from a breeze in the server room. So I apply some tape, in case that fixes the issue. A little while later, shortly before bed … DING-DONG. Ugh.

I have a few hypotheses about the phantom ding-dong that I can test, but in the meantime, the doorbell server isn’t up, but I haven’t put up a new post-it note yet. >_>

Overall reflections

If any store-bought product did exactly what we wanted, I would almost certainly have bought a product instead. However, every doorbell product I looked at was guilty of at least one of these:

Many people might not consider the last one to be a deal-breaker, but personally, I would prefer that:

  1. my devices continue to work even if the company goes out of business and their servers stop running due to an outage,
  2. my devices continue to function even if we’re having an Internet outage,
  3. data from inside my home stay inside my home, and specifically not live in someone else’s servers.

If you want to holler at any IoT product makers to make their products self-hostable, please tweet them at me (@qiqing) – I’d love to help make that happen so I can use their products. Until then, great excuses to follow tutorials and build things myself!

Over the course of working on this project I’ve come to appreciate my strengths and weaknesses, which is important for knowing when to ask for help.

What’s next?

I kept thinking, I’ll write the blog post about this project after I’ve fixed this one bug. But I’ve been one issue away from posting for the last several issues…

Next steps: write a logger. Get some logs. Fix this phantom ding-dong bug. Stay tuned!

Big thanks to Kenton for getting me unstuck, and thanks to Kenton’s Minneapolis friends and other LAN party guests for helping eat all those mints since I needed the container.

Jiggly Cheesecake 0.1

By Jade Wang - 06 Jan 2018

Last month, on my commute, I was rather spellbound by this video from Tasty (Buzzfeed) on the making of the jiggly cheesecake:

So during the first week of my holiday staycation, I decided to give it my own spin. After watching someone else recreate this and the initial reviews, I decided to double the cream cheese (from 4 oz to 8 oz) in the original recipe and otherwise leave the recipe basically unaltered.

And sliced:

Conclusions: it was light, fluffy, and tasty, but didn’t quite taste like “cheesecake.”

Next iteration: double cream cheese again to see what happens.

Starting over from the beginning

By Jade Wang - 05 Jan 2018

It’s time to start over. Starting in 2018, this blog will be largely project-driven, from Arduino hacks to jiggly cheesecakes.

And sometimes, Garply wants to help.

Archive of previous blogs will still live on here: