summaryrefslogtreecommitdiffstats
path: root/_projects/etlas.md
blob: 775aa3110b9883f9b060c1b43e625f13b802e566 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
---
title: "Etlas: e-paper dashboard"
date: 2024-09-05
thumbnail: dash.jpg
layout: post
---

Etlas is a weather, news, and stock price tracking system.

<table style="border: none;">
  <tr style="border: none;">
    <td style="border: none;"><img src="dash.jpg" alt="front" style="width: 100%"></td>
    <td style="border: none;"><img src="pcb.jpg" alt="back" style="width: 100%"></td>
  </tr>
</table>

## Acknowledgements

The e-paper display driver in the epd.c file of the project is derived from <a
href="https://github.com/waveshareteam/e-Paper" class="external"
target="_blank" rel="noopener noreferrer">Waveshare examples</a> for Arduino
and STM32 platforms.

The exceptionally elegant algorithm in the file dht.c, which reads DHT22 sensor
data by comparing consecutive pulses, I ported directly from <a
href="https://github.com/Fonger/ESP8266-RTOS-DHT" class="external"
target="_blank" rel="noopener noreferrer">this</a> implementation for ESP8266
modules to my ESP32. All credit for the algorithm belongs to them.

## Overview

Etlas comprises an embedded system featuring an ESP32 NodeMCU D1
microcontroller, a 7.5″ <a href="https://www.waveshare.com/" class="external"
target="_blank" rel="noopener noreferrer">Waveshare</a> e-paper display, a
DHT22 weather sensor, and a server backend consisting of a FastCGI-wrapped
Flask app. The following diagram outlines this system architecture.

![architecture](etlas_arch.png)

The embedded application, written in C with the help of the ESP-IDF v5.2.1,
connects to a (2.4GHz) WiFi network at startup and obtains time from an NTP
server. It then composites and updates an internal pixel buffer using data
acquired from various data sources and renders to the screen by writing to its
Serial Peripheral Interface.

## Price curves

On the e-paper display, the top-left panel displays end-of-day price curves
over two weeks from the <a href="https://polygon.io/" class="external"
target="_blank" rel="noopener noreferrer">Polygon.io</a> API. The
microcontroller's 512KB SRAM limits the price curves to two weeks. Instead of
using raster images for complex graphics—like e-paper projects often do—Etlas
computes the price curves from CSV data on the fly using the ESP32's 160MHz
microprocessor. To avoid the overhead of floating-point arithmetic, all
computations are performed on integers. The `gui_plot_stocks()` function in the
gui.c file contains the rendering logic.

Proxying the price feeds through the Flask app permits me to configure the
tickers I'm interested in via its application settings. The Flask app cycles
through the tickers in its configuration file as it receives requests from the
embedded software. The Flask app is secured with basic authentication
implemented using htpasswd and OpenBSD's httpd web server. This FastCGI-wrapped
architecture dramatically reduces the complexity of the server code and
increases system reliability.

## News feed

The more prominent panel on the right displays news from <a
href="https://www.channelnewsasia.com/" class="external" target="_blank"
rel="noopener noreferrer">Channel News Asia</a>. The embedded program downloads
and parses the RSS feed before rendering it to the display. The character
glyphs used for rendering news are stored in header files in the sprites
directory as bitmaps. I created the glyphs manually by saving them as images in
GIMP and rasterizing them with ImageMagick.

I connected the embedded system directly to the RSS feed to write less server
code (the focus of this project was the embedded system). In hindsight,
however, it limits the feeds from which Etlas can receive data. In a future
version, I will relay the RSS feed through the backend (like the stock prices)
to make it more flexible.

## Weather data

The bottom panels (middle and right) display the temperature and relative
humidity from a DHT22 sensor. The DHT22 driver, arguably the most interesting
part of the software, reads real-time sensor data by comparing relative pulse
widths. The pulses themselves are too quick for the ESP32 to reliably measure
directly. 

Much of the heavy lifting of acquiring, interpreting, and rendering data from
different data sources is performed on the microcontroller using less than 512
KB of memory. The embedded software that makes that possible is written in C
using the ESP-IDF v5.2.1. My e-paper display driver is a port of Waveshare <a 
href="https://github.com/waveshareteam/e-Paper" class="external"
target="_blank" rel="noopener noreferrer">examples</a> for Arduino
and STM32 platforms. 

I've been using Etlas daily (for a couple of hours on weekdays and all day on
weekends) since August 2024. As of October 2025, it's been running reliably for
over a year.

Files: [source.tar.gz](source.tar.gz)