summaryrefslogtreecommitdiffstats
path: root/_log/etlas.md
blob: 54745f6741ee8f55bbcd490733d0c316a452bf6e (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
---
title: Repurposed the e-reader into a news tracker
date: 2024-09-05
layout: post
project: true
thumbnail: thumb_sm.jpg
---

Repurposed the [e-reader](../e-reader/) for regular use as a news, stocks, and
weather dashboard.

<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>
  <tr style="border: none;">
    <td colspan="2" style="border: none;"><img src="etlas_arch.png" alt="front" style="width: 100%"></td>
  </tr>
</table>

Swapped out the ESP-32-WROOM for an ESP32 NodeMCU D1—smaller, better form
factor. Connected a DHT22 sensor for temperature and humidity data.

Weather: 26µs/50µs/70µs pulses from the DHT22's single-wire protocol are too
fast for ESP32 standard APIs. Ported <a
href="https://github.com/Fonger/ESP8266-RTOS-DHT" class="external"
target="_blank" rel="noopener noreferrer">this</a> clever bit-banging from
ESP8266 to ESP32:

```
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[BUFLEN])
{
    /* init code and preamble */

    for (i = 0; i < BUFLEN; 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;
}
```

Stocks: Obtained two weeks EOD data from Polygon.io—maximum possible with 512
KB RAM. Deployed a simple Flask API on VPS to manage the watchlist and relay
the feed. Wrapped the API in FastCGI and exposed it through chroot-ed 
htpasswd + slowcgi + httpd—battle-tested OpenBSD base-system tools.

Custom stepped graph works but the code is crude. vTaskDelay() is needed to
keep the watchdog timer from triggering—revisit with Bresenham's line
algorithm.

News: Used Channel NewsAsia RSS feed for news. Hand-coded the XML parsing in
C—no Flask backend at the time. Now that I have one for stocks, will move the
feed through the Flask backend in the next revision.

epd_init() stalled intermittently on first refresh() after flash. Toggling
delay values in refresh() resolved it. If the first refresh succeeded, system
remained stable. Could not find the root cause. Suspect noisy supply due to
powering display via MCU.

Commit: <a
href="https://git.asciimx.com/etlas/commit/?id=a92c86ac1592c2137d3d1fec1668eacc2d0ca581"
class="external" target="_blank" rel="noopener noreferrer">a92c86a</a>.