forked from arendst/Tasmota
-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathepaper29.tc
More file actions
231 lines (200 loc) · 6.57 KB
/
Copy pathepaper29.tc
File metadata and controls
231 lines (200 loc) · 6.57 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// EPaper 2.9" Display Controller & Data Logger
// Sensors + EPaper display + 24h logging + WebChart + UDP globals
// 24h data logging arrays (96 x 15-min intervals)
// Data lives in [0..95] (the 15-min slot of the day, last_m15-1); the charts
// read arr[0..95] so all 96 slots show with no spurious leading 0. (Arrays sized
// [97] for back-compat with the older .bin layout; index 96 is now unused.)
// Stored in a dedicated .bin (NOT .pvs): .pvs is unreliable for chart arrays, so
// we own the file and fileWriteBin/fileReadBin it -- mirrors sml_chart_pv_save().
float aco2[97];
float atvc[97];
float tmpa[97];
float axhum[97];
#define CHART_FILE "/epaper29_chart.bin"
// Sensor readings — shared via UDP (auto-send on assignment)
global float wtemp = 0.0;
global float whumi = 0.0;
global float wtvoc = 0.0;
global float wco2 = 0.0;
// Local sensor readings (not shared)
float eco2 = 0;
float ahum = 0.0;
// Received via UDP from other devices
global float bpress = 0.0;
global float sedc = 0.0;
global float wrga = 0.0;
global float wrgh = 0.0;
global float wrgg = 0.0;
global float atmp = 0.0;
global float pwl = 0.0;
// Averaging accumulators
float tmps = 0.0;
float hums = 0.0;
float tvcs = 0.0;
float co2s = 0.0;
int mcnt = 0;
// State
int last_m15 = -1;
int cnt = 0;
char dt[128];
char lbl[32];
// Persist the four 24h chart rings to their own binary file (mirrors
// sml_chart_pv_save()). Called on the 15-min tick instead of saveVars().
void epaper_chart_save() {
int h = fileOpen(CHART_FILE, "w");
if (h < 0) return;
fileWriteBin(h, aco2, 97);
fileWriteBin(h, atvc, 97);
fileWriteBin(h, tmpa, 97);
fileWriteBin(h, axhum, 97);
fileClose(h);
}
void epaper_chart_load() {
int h = fileOpen(CHART_FILE, "r");
if (h < 0) return; // first run: arrays stay zero
fileReadBin(h, aco2, 97);
fileReadBin(h, atvc, 97);
fileReadBin(h, tmpa, 97);
fileReadBin(h, axhum, 97);
fileClose(h);
}
void read_sensors() {
wtemp = sensorGet("BME280#Temperature");
whumi = sensorGet("BME280#Humidity");
bpress = sensorGet("BME280#Pressure");
wtvoc = sensorGet("SGP30#TVOC");
eco2 = sensorGet("SGP30#eCO2");
ahum = sensorGet("BME280#AbsHumidity");
wco2 = sensorGet("SCD30#CarbonDioxide");
}
void update_display() {
// Row 1: Temperature, Humidity, Pressure, Time
sprintf(dt, "[f1p7x0y5]%.1f C", wtemp);
dspText(dt);
sprintf(dt, "[p7x70y5]%.1f %% [x250y5t] ", whumi);
dspText(dt);
//dspText("[x250y5t]");
sprintf(dt, "[p11x140y5]%.1f hPa", bpress);
dspText(dt);
// Row 2: TVOC, eCO2, Abs Humidity
sprintf(dt, "[p18x30y25]TVOC: %.1f ppb", wtvoc);
dspText(dt);
sprintf(dt, "[p18x160y25]eCO2: %.1f ppm", eco2);
dspText(dt);
sprintf(dt, "[p18c26l5]ahum: %.1f g^m3", ahum);
dspText(dt);
// solar inverters
sprintf(dt, "[p25c1l5]WR 1 (Dach) : %.1f W", sedc);
dspText(dt);
sprintf(dt, "[p25c1l6]WR 2 (Garage): %.1f W", -wrga);
dspText(dt);
sprintf(dt, "[p25c1l7]WR 3 (G-Haus): %.1f W", -wrgh);
dspText(dt);
sprintf(dt, "[p25c1l8]WR 4 (Garten): %.1f W", -wrgg);
dspText(dt);
// CO2
sprintf(dt, "[p25c1l10]CO2 : %.0f ppm", wco2);
dspText(dt);
sprintf(dt, "[x170y95r120:30f2p6x185y100] %.0f %", pwl);
dspText(dt);
sprintf(dt, "[f0s2p10x210y70] %.0f C", atmp);
dspText(dt);
// Flush to EPaper
dspText("[d]");
}
void EverySecond() {
read_sensors();
cnt = cnt + 1;
// Accumulate for averaging
tmps = tmps + wtemp;
hums = hums + whumi;
tvcs = tvcs + wtvoc;
co2s = co2s + wco2;
mcnt = mcnt + 1;
// 15-minute data logging
int m15 = (tasm_hour * 60 + tasm_minute) / 15 + 1;
if (m15 != last_m15 && last_m15 > 0) {
if (mcnt > 0) {
aco2[last_m15 - 1] = co2s / (float)mcnt; // store 0-based: slot 1..96 -> index 0..95
atvc[last_m15 - 1] = tvcs / (float)mcnt;
tmpa[last_m15 - 1] = tmps / (float)mcnt;
axhum[last_m15 - 1] = hums / (float)mcnt;
epaper_chart_save();
}
mcnt = 0;
co2s = 0.0;
tvcs = 0.0;
tmps = 0.0;
hums = 0.0;
}
last_m15 = m15;
// Sync graph position with time
int pos = m15;
if (pos >= 96) {
pos = 0;
}
// Update display every 10 seconds
int ups = tasm_uptime;
if (ups % 10 == 0) {
update_display();
}
// EPaper refresh every 5 min (prevent ghosting)
if (ups % 300 == 0) {
dspText("[Id]");
dspText("[id]");
}
// Sensor readings auto-send via UDP on assignment (global float)
}
void web_label(int idx) {
LGetString(idx, lbl);
dt = "{s}";
dt += lbl;
dt += "{m}";
webSend(dt);
}
void WebCall() {
web_label(0);
sprintf(dt, "%.1f C{e}", wtemp);
webSend(dt);
web_label(1);
sprintf(dt, "%.1f %{e}", whumi);
webSend(dt);
web_label(20);
sprintf(dt, "%.1f g/m3{e}", ahum);
webSend(dt);
web_label(4);
sprintf(dt, "%.0f ppm{e}", wco2);
webSend(dt);
web_label(2);
sprintf(dt, "%.1f hPa{e}", bpress);
webSend(dt);
sprintf(dt, "{s}Heap{m}%d kb{e}", tasm_heap/1024);
webSend(dt);
}
void WebPage() {
// Frame the charts in a card (WebPage is not auto-carded like WebCall slots).
webSend("<fieldset style='border:1px solid rgba(150,150,150,.4);border-radius:8px;margin:5px 2px;padding:2px 9px 8px'><legend style='font-size:11px;opacity:.55;padding:0 5px'>slot 4 charts</legend>");
webSend("<div style='margin-left:-30px'>");
int cpos = last_m15 - 1; // chart write-head: one past the newest WRITTEN slot
if (cpos < 0) { cpos = 0; } // (arr[last_m15-1] is the current, still-accumulating slot)
WebChartSize(640, 200);
// Dual Y-axis: TVOC (left 0-3000 ppb) + CO2 (right 0-2000 ppm)
WebChart(0, "Air Quality", "TVOC|ppb", 0xFF0000, cpos, 96,atvc, 0, 15, 0.0, 3000.0);
WebChart(0, "", "CO2|ppm", 0x0000FF, cpos, 96,aco2, 0, 15, 0.0, 2000.0);
// Dual Y-axis: Humidity (left 0-100 %) + Temperature (right 0-40 C)
WebChart(0, "Climate", "Humidity|%", 0xFF0000, cpos, 96,axhum, 1, 15, 0.0, 100.0);
WebChart(0, "", "Temperature|C", 0x0000FF, cpos, 96,tmpa, 1, 15, 0.0, 40.0);
webSend("</div>");
webSend("</fieldset>");
}
int main() {
epaper_chart_load(); // restore the chart rings from CHART_FILE
// Initial display setup: clear, draw separator lines
dspText("[zD0]");
dspText("[x0y20h296x0y40h296]");
dspText("[d]");
// Set initial time slot
last_m15 = (tasm_hour * 60 + tasm_minute) / 15 + 1;
print("EPaper display started\n");
return 0;
}