MycilaJSY 13.0.0
Arduino / ESP32 library for the JSY1031, JSY-MK-163, JSY-MK-193, JSY-MK-194, JSY-MK-227, JSY-MK-229, JSY-MK-333 families single-phase and three-phase AC bidirectional meters from Shenzhen Jiansiyan Technologies Co, Ltd.
Loading...
Searching...
No Matches
MycilaDimmer.cpp
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright (C) 2023-2025 Mathieu Carbou
4 */
5#include <MycilaDimmer.h>
6
7#define DIMMER_RESOLUTION 12
8#define FIRING_DELAYS_LEN 200U
9
10static constexpr uint32_t FIRING_DELAY_MAX = (1 << DIMMER_RESOLUTION) - 1;
11static constexpr uint32_t FIRING_DELAYS_SCALE = (FIRING_DELAYS_LEN - 1U) * (1UL << (16 - DIMMER_RESOLUTION));
12static constexpr uint16_t FIRING_DELAYS[FIRING_DELAYS_LEN] = {
13 0xffff,
14 0xe877,
15 0xe240,
16 0xddd9,
17 0xda51,
18 0xd74f,
19 0xd4aa,
20 0xd248,
21 0xd01a,
22 0xce16,
23 0xcc34,
24 0xca6e,
25 0xc8c0,
26 0xc728,
27 0xc5a1,
28 0xc42b,
29 0xc2c3,
30 0xc168,
31 0xc019,
32 0xbed3,
33 0xbd98,
34 0xbc65,
35 0xbb3b,
36 0xba17,
37 0xb8fb,
38 0xb7e5,
39 0xb6d5,
40 0xb5ca,
41 0xb4c5,
42 0xb3c4,
43 0xb2c8,
44 0xb1d1,
45 0xb0dd,
46 0xafed,
47 0xaf01,
48 0xae18,
49 0xad33,
50 0xac51,
51 0xab71,
52 0xaa95,
53 0xa9bb,
54 0xa8e3,
55 0xa80e,
56 0xa73b,
57 0xa66b,
58 0xa59c,
59 0xa4d0,
60 0xa406,
61 0xa33d,
62 0xa276,
63 0xa1b1,
64 0xa0ed,
65 0xa02b,
66 0x9f6b,
67 0x9eac,
68 0x9dee,
69 0x9d32,
70 0x9c76,
71 0x9bbc,
72 0x9b04,
73 0x9a4c,
74 0x9996,
75 0x98e0,
76 0x982b,
77 0x9778,
78 0x96c5,
79 0x9613,
80 0x9563,
81 0x94b2,
82 0x9403,
83 0x9354,
84 0x92a6,
85 0x91f9,
86 0x914c,
87 0x90a0,
88 0x8ff5,
89 0x8f4a,
90 0x8ea0,
91 0x8df6,
92 0x8d4d,
93 0x8ca4,
94 0x8bfb,
95 0x8b53,
96 0x8aab,
97 0x8a04,
98 0x895d,
99 0x88b6,
100 0x8810,
101 0x876a,
102 0x86c4,
103 0x861e,
104 0x8579,
105 0x84d3,
106 0x842e,
107 0x8389,
108 0x82e4,
109 0x823f,
110 0x819b,
111 0x80f6,
112 0x8051,
113 0x7fad,
114 0x7f08,
115 0x7e63,
116 0x7dbf,
117 0x7d1a,
118 0x7c75,
119 0x7bd0,
120 0x7b2b,
121 0x7a85,
122 0x79e0,
123 0x793a,
124 0x7894,
125 0x77ee,
126 0x7748,
127 0x76a1,
128 0x75fa,
129 0x7553,
130 0x74ab,
131 0x7403,
132 0x735a,
133 0x72b1,
134 0x7208,
135 0x715e,
136 0x70b4,
137 0x7009,
138 0x6f5e,
139 0x6eb2,
140 0x6e05,
141 0x6d58,
142 0x6caa,
143 0x6bfb,
144 0x6b4c,
145 0x6a9b,
146 0x69eb,
147 0x6939,
148 0x6886,
149 0x67d3,
150 0x671e,
151 0x6668,
152 0x65b2,
153 0x64fa,
154 0x6442,
155 0x6388,
156 0x62cc,
157 0x6210,
158 0x6152,
159 0x6093,
160 0x5fd3,
161 0x5f11,
162 0x5e4d,
163 0x5d88,
164 0x5cc1,
165 0x5bf8,
166 0x5b2e,
167 0x5a62,
168 0x5993,
169 0x58c3,
170 0x57f0,
171 0x571b,
172 0x5643,
173 0x5569,
174 0x548d,
175 0x53ad,
176 0x52cb,
177 0x51e6,
178 0x50fd,
179 0x5011,
180 0x4f21,
181 0x4e2d,
182 0x4d36,
183 0x4c3a,
184 0x4b39,
185 0x4a34,
186 0x4929,
187 0x4819,
188 0x4703,
189 0x45e7,
190 0x44c3,
191 0x4399,
192 0x4266,
193 0x412b,
194 0x3fe5,
195 0x3e96,
196 0x3d3b,
197 0x3bd3,
198 0x3a5d,
199 0x38d6,
200 0x373e,
201 0x3590,
202 0x33ca,
203 0x31e8,
204 0x2fe4,
205 0x2db6,
206 0x2b54,
207 0x28af,
208 0x25ad,
209 0x2225,
210 0x1dbe,
211 0x1787,
212 0x0000};
213
214// =============================================================================
215// Mycila::Dimmer
216// =============================================================================
217
218uint16_t Mycila::Dimmer::_lookupFiringDelay(float dutyCycle, uint16_t semiPeriod) {
219 uint32_t duty = dutyCycle * FIRING_DELAY_MAX;
220 uint32_t slot = duty * FIRING_DELAYS_SCALE + (FIRING_DELAYS_SCALE >> 1);
221 uint32_t index = slot >> 16;
222 uint32_t a = FIRING_DELAYS[index];
223 uint32_t b = FIRING_DELAYS[index + 1];
224 uint32_t delay = a - (((a - b) * (slot & 0xffff)) >> 16); // interpolate a b
225 return (delay * semiPeriod) >> 16; // scale to period
226}
227
228#ifdef MYCILA_JSON_SUPPORT
229static const char* H_LEVELS[] = {"H1", "H3", "H5", "H7", "H9", "H11", "H13", "H15", "H17", "H19", "H21"};
230
236void Mycila::Dimmer::toJson(const JsonObject& root) const {
237 root["type"] = type();
238 root["enabled"] = _enabled;
239 root["online"] = _online;
240 root["state"] = isOn() ? "on" : "off";
241 root["duty_cycle"] = _dutyCycle;
242 root["duty_cycle_mapped"] = getDutyCycleMapped();
243 root["duty_cycle_fire"] = _dutyCycleFire;
244 root["duty_cycle_limit"] = _dutyCycleLimit;
245 root["duty_cycle_min"] = _dutyCycleMin;
246 root["duty_cycle_max"] = _dutyCycleMax;
247 root["power_lut"] = _powerLUTEnabled;
248 root["power_lut_semi_period"] = _semiPeriod;
249 JsonObject harmonics = root["harmonics"].to<JsonObject>();
250 float* output = new float[11]; // H1 to H21
251 if (calculateHarmonics(output, 11)) {
252 for (size_t i = 0; i < 11; i++) {
253 if (!std::isnan(output[i])) {
254 harmonics[H_LEVELS[i]] = output[i];
255 }
256 }
257 }
258}
259#endif