ETLAS: E-PAPER DASHBOARD

05 SEPTEMBER 2024

Etlas is a news, stock market, and weather tracker powered by an ESP32 NodeMCU D1, featuring a 7.5-inch Waveshare e-paper display and a DHT22 sensor module.

front back

The top-left panel shows two weeks of end-of-day prices—the maximum the ESP32’s SRAM can hold—from the Polygon.io API. The price feed is relayed through a FastCGI-wrapped Flask app hosted on a VPS. This lets me configure stock symbols in its application settings. The app cycles through them as requests come in from the ESP32. Running the Flask app as a FastCGI process while exposing it via httpd with htpasswd authentication keeps the server code simple and secure.

The following diagram outlines the Etlas’s overall system architecture.

architecture

The more prominent panel on the right of the display shows local and world news from Channel NewsAsia. The MCU downloads and parses XML data from the RSS feed directly before rendering it to the display. The character glyphs used are stored as bitmaps in the sprites directory. I skipped the proxy for news to avoid writing more server code, but in hindsight it limits the feeds Etlas can handle. I will fix this in a future version.

The middle and bottom right panels display the temperature and relative humidity from the DHT22 sensor. The DHT22 uses pulse-width modulation to transmit data to the host. The 26µs, 50µs, and 70µs pulses are too fast for the ESP32 to measure reliably with standard APIs. Instead, the driver compares relative pulse widths to differentiate zeros from ones:

static inline int dht_await_pin_state(int state, int timeout)
{
    int t;
    static const uint16_t delta = 1;

    for (t = 0; t < timeout; t += delta) {
        ets_delay_us(delta);
        if (gpio_get_level(DHT_PIN) == state)
          return t;
    }
    return 0;
}

static inline int dht_get_raw_data(unsigned char buf[DHT_DATA_LEN])
{
    int rc;
    unsigned char i, pwl, pwh;

    gpio_set_level(DHT_PIN, 0);
    ets_delay_us(1100);
    gpio_set_level(DHT_PIN, 1);

    if (!dht_await_pin_state(0, 40)) {
        rc = 1;
        xQueueSend(dht_evt_queue, &rc, (TickType_t) 0);
        return 0;
    }
    if (!dht_await_pin_state(1, 80)) {
        rc = 2;
        xQueueSend(dht_evt_queue, &rc, (TickType_t) 0);
        return 0;
    }
    if (!dht_await_pin_state(0, 80)) {
        rc = 3;
        xQueueSend(dht_evt_queue, &rc, (TickType_t) 0);
        return 0;
    }

    for (i = 0; i < DHT_DATA_LEN; i++) {
        if (!(pwl = dht_await_pin_state(1, 50))) {
            rc = 4;
            xQueueSend(dht_evt_queue, &rc, (TickType_t) 0);
            return 0;
        }
        if (!(pwh = dht_await_pin_state(0, 70))) {
            rc = 5;
            xQueueSend(dht_evt_queue, &rc, (TickType_t) 0);
            return 0;
        }
        buf[i] = pwh > pwl;
    }
    return 1;
}

I ported this implementation from ESP8266 to ESP32—all credit for the algorithm belongs to them.

Etlas is a networked embedded system. All acquisition, processing, and rendering of data are performed on the ESP32’s 160MHz microprocessor using less than 512KB of SRAM. The embedded software that makes this possible is written in C using ESP-IDF v5.2.1. The e-paper display driver is derived from Waveshare examples for Arduino and STM32 platforms.

Etlas has been running reliably for over a year since August 2024.

Files: source.tar.gz