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
103
|
<p>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.</p>
<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>
<p>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.</p>
<p>The following diagram outlines the Etlas’s overall system architecture.</p>
<p><img src="etlas_arch.png" alt="architecture" /></p>
<p>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.</p>
<p>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:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>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;
}
</code></pre></div></div>
<p>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.</p>
<p>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.</p>
<p>Etlas has been running reliably for over a year since August 2024.</p>
<p>Files: <a href="source.tar.gz">source.tar.gz</a></p>
|