diff options
Diffstat (limited to '_projects/etlas.md')
| -rw-r--r-- | _projects/etlas.md | 174 |
1 files changed, 93 insertions, 81 deletions
diff --git a/_projects/etlas.md b/_projects/etlas.md index 775aa31..e402b05 100644 --- a/_projects/etlas.md +++ b/_projects/etlas.md @@ -5,7 +5,10 @@ thumbnail: dash.jpg layout: post --- -Etlas is a weather, news, and stock price tracking system. +Etlas is a news, stock market, and weather tracker powered by an ESP32 NodeMCU +D1, featuring a 7.5-inch <a href="https://www.waveshare.com/" class="external" +target="_blank" rel="noopener noreferrer">Waveshare</a> e-paper display and a +DHT22 sensor module. <table style="border: none;"> <tr style="border: none;"> @@ -14,89 +17,98 @@ Etlas is a weather, news, and stock price tracking system. </tr> </table> -## Acknowledgements +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 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. +The following diagram outlines the Etlas's overall system architecture.  -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. +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 <a href="https://github.com/Fonger/ESP8266-RTOS-DHT" class="external" +target="_blank" rel="noopener noreferrer">this</a> 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 +<a href="https://github.com/waveshareteam/e-Paper" class="external" +target="_blank" rel="noopener noreferrer">examples</a> for Arduino and STM32 +platforms. + +Etlas has been running reliably for over a year since August 2024. Files: [source.tar.gz](source.tar.gz) |
