Mom Calendar with Adafruit MagTag

I bought an Adafruit MagTag last year, wanting to play with E-Ink technology. E-Ink, also known as "electronic paper", is a display device that mimics the appearance of paper. A special property of E-Ink is that, it only consumes electricity for changing the displayed content, but does not need electricity to retain the text and images it's already showing. This type of display is often found on E-Readers such as the Amazon Kindle (paid link), where the content doesn't change rapidly and the user would be looking at the same content for several minutes or longer.

After three years of pandemic flight restrictions, my mother was finally able to come from Shanghai and visit me in Maryland. She was here for 70 days, arriving on March 08 and departing on May 17. When I was cleaning the apartment prior to her arrival, I noticed the blank E-Ink display on my wall, and decided to build a calendar that counts mom's visit.

Adafruit MagTag displaying "43"

Mom Calendar - Features

The mom calendar shall display number of days since mom's arrival. The day counter starts from 0 on March 08, increments by 1 on each day, and reaches 70 on May 17.

Adafruit MagTag contains a tiny 420mAh lithium-ion battery. Since there isn't a power supply on my wall, the gadget I built must consume as little power as possible, so that the battery can last at least a few weeks.

Mom Calendar - Design

Adafruit MagTag, when purchased as a starter kit, is a fully integrated product. There's no design necessary on the hardware side.

To achieve the desired effect on the software side, the Arduino sketch should:

  1. Determine the current date.
  2. Calculate what day it is during mom's visit.
  3. Draw the day count on the E-Ink display.

In order to maximize power saving:

  • Unused components on the MagTag, such as a speaker and colorful NeoPixels, are powered off.
  • The ESP32-S2 microcontroller is kept in deep sleep mode most of the time. It wakes up every 30 minutes to perform updates.

Both mom and I go to bed well before midnight. Although the day count is supposed to increment at midnight, it is unnecessary to keep this precise time because neither of us would see it. Therefore, I relaxed the requirement and allowed the increment to occur at any time between midnight and early morning. This not only allowed for longer 30-minute sleeps, but also enabled a simplification that ignores the timezone differences caused by Daylight Savings Time (DST).

Mom Calendar - Arduino Sketch

#include <Adafruit_ThinkInk.h>
#include <WiFi.h>

const char* WIFI_SSID = "ssid";
const char* WIFI_PASS = "passw0rd";

ThinkInk_290_Grayscale4_T5 display(EPD_DC, EPD_RESET, EPD_CS, -1, -1);

static void shutdown()
{
  ESP.deepSleep(1800*1000000);
}

void setup() {
  // disable speaker, NeoPixel, light sensor
  pinMode(SPEAKER_SHUTDOWN, OUTPUT);
  digitalWrite(SPEAKER_SHUTDOWN, LOW);
  pinMode(NEOPIXEL_POWER, OUTPUT);
  digitalWrite(NEOPIXEL_POWER, HIGH);

  Serial.begin(115200);
  delay(100);

  // connect to WiFi
  WiFi.persistent(false);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.printf("WiFi.status %" PRIu8 "\n", WiFi.status());
    return shutdown();
  }

  // NTP sync
  configTime(-5*3600, -4*3600, "time.nist.gov", "pool.ntp.org");
  struct tm tm;
  if (!getLocalTime(&tm, 5000)) {
    Serial.println("NTP failed");
    return shutdown();
  }

  time_t t = time(nullptr);
  Serial.printf("t=%ld\n", static_cast<long>(t));

  // display day count
  display.begin(THINKINK_MONO);
  display.clearBuffer();
  display.setTextSize(10);
  display.setTextColor(EPD_GRAY);
  display.setCursor(40, 20);
  display.print((t - 1678258800) / 86400);
  display.display(true);
  delay(2000);
  shutdown();
}

void loop() {
}

The main logic of this code is in the setup() function that executes once after the microcontroller boots or wakes up. It first turns off any unused peripherals to save power, then connects to WiFi and updates system clock from NTP servers, and finally calculates and displays the day count. In all execution paths, the function ends with ESP.deepSleep(), putting the microcontroller back to sleep mode, regardless of whether the time update was successful.

The timestamp 1678258800 refers to March 08 2AM Eastern Standard Time, so that the day of mom's arrival is calculated as day 0. We coders count from zero!

The display logic required some trial and error when I developed this code. In particular, the text size, "color", and cursor position must be tested on the device to achieve the desired effect. Moreover, the delay(2000) after the display update is necessary. Without it, the microcontroller would be powered off too quickly, leaving the E-Ink display blank.

Conclusion

I built a calendar that counts how many days mom has been visiting me, on an Adafruit MagTag E-Ink display module controlled by ESP32-S2 WiFi microcontroller. Mom was delighted once she found out what the number on the wall represents, but started to get sad when the counter approached 70 when she was scheduled to return to her home.

The Arduino sketch was designed to consume as little battery power as possible. Eventually, the battery lasted 44 days before it required recharging.

Join the discussion: Hackster