Oregon Vacation (2) GC12 and GC17

On Jun 07, I flew to Portland, Oregon and started my 7-day vacation. Oregon is where the sport of geocaching got started, and my primary goal in Oregon is to find some of the world's oldest geocaches. Saturday Jun 08, the weather was less than perfect compared to next few days. However, I couldn't control my excitement and decided to nab the important geocaches first.

Planning for GC12

GC12, formerly known as GPS Stash #8, was hidden on 12 May 2000, nineteen years ago. It is Oregon's oldest active geocache, and as I later learned, the second oldest active geocache in the world.

When I was doing my initial trip planning, Google Maps says I could drive right to it. Upon closer inspection, oh well, I would have to drive over a "road block".

Google Maps route for GC12

Oregon Vacation (1) Planning and Departure

I had a 7-day vacation in northwestern Oregon in June 2019. This is the biggest solo road trip I've ever had so far.

Why Oregon?

Earlier this year, Alaska Airlines messed up with my flight, and then I received a $200 voucher. The voucher entitles me to a free flight to west coast.

Alaska flies to five cities on the west coast:

  • Seattle, Washington
  • Portland, Oregon
  • San Francisco, California
  • Los Angeles, California
  • San Diego, California

How to Install OpenWrt 18.06 on Onion Omega2 Pro

I bought a GL-AR750 home router (paid link) last year, and was very happy with the flexibility of its OpenWrt operating system. The base system has enough functionality as a home router: it has a web-based configuration interface; WiFi works out of box without fiddling hostapd.conf. On the other hand, the system is extensible that I can install additional packages to add VPN server, file sharing, etc. When I decide to start hacking, I noticed a problem: the GL-AR750 is now part of my "production" network, and I don't want to change it too much to affect my normal life. Thus, it's time for a second OpenWrt router!

After some online search and comparison, I chose the Onion Omega2 Pro. The strengths of Onion Omega2 Pro are:

  • The CPU is MIPS architecture, allowing me to gain some experience with this unfamiliar architecture.
  • It has 8GB eMMC storage, giving me plenty of space to install packages.
  • It has LiPo battery port, USB host port, and pin headers with SPI and I2C, leaving possibility of building battery-powered IoT projects.

Shipment arrived two months later. I plugged it in, and found that the Omega2 Pro runs OnionOS, a customized version of OpenWrt. Apart from GUI differences, it uses a custom WiFi driver wifi-warp-core that has several flaws. Most notably, my WiFi SSID is + (a plus sign), and the Onion would not connect to it.

screenshot of OnionOS on Omega2 Pro

Geocaching is All About Expanding My Comfort Zone

I started geocaching as a hobby in 2013. Since then, I have found more than 1000 caches across 18 US states as well as in China. During these years, I stepped out my comfort zone several times, and became a more experienced geocacher.


Geocaches come with different types. Traditional is the most common type: the webpage of a Traditional cache has its coordinates, and I can straightforwardly find the physical container at that location. Another common type is a Multi: I need to visit a location, collect information such as reading text from a plague or counting the number of windows, and then find the physical container at a different location whose waypoint is computed from the answers from the first location. I'm quite familiar with these types.

One geocache type I'm uncomfortable with is Mystery puzzle cache. These caches are published with bogus published coordinates, but the webpage contains clues to find the real coordinates of the physical container. The puzzle could be a piece of cipher text, a crossword puzzle, a strange picture, or something else. Although I know a thing or two about classic ciphers, I could not get a hold of them.

This all changed when Geocaching HQ assigned me a mission to find a puzzle cache in August 2014:

Air602 Weather Indicator

Air602 is a 2.4GHz Wi-Fi module based on Winner Micro W600 system-on-chip. Being a new release, it has limited software support. It took me more than a day to make it blink.

Naturally, the next step is to connect a sensor. I decide to reproduce the ESP8266 weather indicator but with Air602 instead.

Air602 Board Pinout

The Air602 development board, labelled EVB_W602_A11, has six pins:

Air602 pin W600 pin
RX1 PB11
TX1 PB12

Air602 Hands On and Blink with C SDK

I hear there's a new WiFi microcontroller that is cheaper than ESP8266's "unbeatable" low price tag. It is the Air602, a 2.4GHz Wi-Fi module based on Winner Micro W600 system-on-chip.

Buying an Air602

Currently, Seeed Studio is the only seller for this module. It comes as a bare module for $1.90, or a development board for $2.90. The bare module lacks an antenna and requires surface mount soldering that I'm not comfortable with, so I purchased the development board version that comes with antenna, power regulator, and USB-UART chip.

photo of Air602 development board

My order was shipped from Hong Kong, and it took about two months for the order to arrive United States.

Is Junxiao in the Room? Presence Detection with nRF52 Bluefruit

I recently obtained some Adafruit Feather nRF52 Bluefruit LE (paid link) boards. The main chip on this board is the nRF52832 from Nordic, which offers Bluetooth Low Energy (BLE) communication, but does not have WiFi. Adafruit made a nice Arduino core for nRF52, so that it can be programmed easily with the familiar Arduino environment.

Incidentally, this isn't the first BLE device I have. Many small battery-powered devices, including the Fitbit Alta HR tracker (paid link) I wear daily, uses BLE for communication. This means, I could use the nRF52 board to answer one question: is Junxiao in the room?

#include <bluefruit.h>

// UUID of Fitbit Alta HR: ADABFB00-6E7D-4601-BDA2-BFFAA68956BA
const uint8_t FITBIT_UUID[] = {
  0xBA, 0x56, 0x89, 0xA6, 0xFA, 0xBF, 0xA2, 0xBD,
  0x01, 0x46, 0x7D, 0x6E, 0x00, 0xFB, 0xAB, 0xAD,

unsigned long lastReport = -1;

void setup()

  Bluefruit.begin(0, 0);


void scan_callback(ble_gap_evt_adv_report_t* report)
  unsigned long now = millis();

  Serial.printf("%09d ", now);
  Serial.printBufferReverse(report->peer_addr.addr, 6, ':');
  Serial.printf(" %d\n", report->rssi);

  lastReport = now;

void loop()
  digitalWrite(LED_BUILTIN, millis() < lastReport + 5000);

This sketch initializes a BLE scanner. filterUuid asks the scanner to invoke scan_callback function whenever it receives an advertisement from a Fitbit Alta HR, identified by the service UUID ADABFB00-6E7D-4601-BDA2-BFFAA68956BA (readable by Bluefruit app for iPad). useActiveScan(false) configures the scanner to passively listen for periodical advertisement packets without transmitting "scan request" packets, to conserve battery on my wristband. When a "report" (scan_callback invocation) is received, the red LED is lit for five seconds.

In practive, it works OK. When I'm within 10 meters from the Bluefruit board, the LED lights up frequently, but it's not consecutive because the Fitbit does not advertise itself very often. If I put my Fitbit into the microwave (paid link) acting as a Faraday cage, the onboard LED no longer lights up. Oops, I got to run before my Fitbit gets fried in the microwave!

Loud Pumpkin with Circuit Playground

It's October. Pumpkins are filling the grocery stores. This means one thing: Halloween is coming!

I'm told that I'm supposed to wear a costume on Halloween. However, I'm too broke to buy an outfit for just one day, so I'm going to wear a colorful circuit board instead. This year, I'm going to become a pumpkin. Well, sorta.

The board is an Adafruit Circuit Playground Express. It packs 10 NeoPixel LEDs that can display any color, four sensors, and a few buttons. My code uses the microphone sensor to measure how loud is the environment. Based on measured sound pressure, it then lights up a number of NeoPixels to #ff7619 the "pumpkin color".

#include <Adafruit_CircuitPlayground.h>

void setup() {

void loop() {
  float sp = CircuitPlayground.mic.soundPressureLevel(100);
  int peak = map(sp, 56, 90, 0, 9);

  for (int i = 0; i <= peak; ++i) {
    CircuitPlayground.strip.setPixelColor(i, 0xff7619);

ESP8266 Call Button

It's NDN Community Meeting again and this time I'm officially presenting HomeCam at the demo session. I'm the sole presenter of this project. Normally, I have to stay at my table to show my project to the audience. However, I don't want to miss the chance of seeing what others have been doing. To solve this dilemma, I come up with an idea: a call button.

I put a big button on my table. It is labelled as: if I'm not here, press the button to send an Interest. Then, I wear a battery powered light ring on my body. Whenever someone presses the button, it lights up for 15 seconds.

me wearing a light ring at NDNcomm demo session

How It Works

Both the button and the light ring are based on ESP8266. The light ring unit acts as WiFi access point and NDN producer. The button unit acts as WiFi station and NDN consumer. When the button is pressed, the consumer transmits a signed Interest, and the producer turns on the light for 15 seconds after verifying the signature. Since the light ring unit is battery-powered, it enters deep sleep mode if there's no connected WiFi client.


1998年,我参加小学生作文竞赛时写下了一篇《二十一世纪电视畅想》。 20年过去了,让我们来看看,这些畅想变成现实了吗?

小朋友们,你们想过没有二十一世纪的电视是怎样的呢? 我学习之余,常在潜心研究、精心设计着它们呢。我告诉大家,到那时的电视机呀,小的只有手表这么小,大的足有三层楼高。

在二十一世纪,“手表这么小”的电视机称为“智能手表”。 它们不能直接接收电视信号,而是接入移动通讯网络,通过因特网可以观看电视。

“三层楼高”的电视机在广告业已经普及。 纽约时报广场就有多幅大型电视屏幕,每天24小时播放广告: