summaryrefslogtreecommitdiffstats
path: root/_log/etlas.md
blob: 7201572e1dca3857f7984546291b9cc92653097b (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
103
104
105
---
title: "Etlas: e-paper dashboard"
date: 2024-09-05
layout: post
project: true
thumbnail: thumb_sm.jpg
---

Repurposed [e-reader](../e-reader/) into something for regular use. News,
stocks, weather dashboard. ESP32 NodeMCU D1 + 7.5" Waveshare e-paper + DHT22
sensor.

<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>

Stocks: Two weeks EOD data (max possible) from Polygon.io. Flask app on VPS
manages watchlist, relays feed. Backend: httpd + htpasswd + slowcgi + Flask.

gui_plot_stocks() draws stepped graph. Was easier to implement, but the code is
hideous—vTaskDelay() needed to prevent watchdog timer from triggering.

NOTE: Bresenham’s?

News: Channel NewsAsia RSS. MCU parses feed. Didn't plan to have a backend at
the time. Now that I have one for stocks, should relay feed for flexibility.

Weather: DHT22 single-wire protocol. 26µs/50µs/70µs pulses are too fast for
standard ESP32 APIs. Bit-banged relative pulse widths (ported from <a
href="https://github.com/Fonger/ESP8266-RTOS-DHT" class="external"
target="_blank" rel="noopener noreferrer">ESP8266</a>):

```
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])
{
    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 < 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;
}
```

epd_init() stalls intermittently on first refresh() after flash. Toggling delay
values in refresh() resolves it. If the first refresh succeeds, system remains
stable. Root cause unknown—suspect noisy supply due to powering display via
MCU.

Uptime: August 2024 - February 2026

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