Compare commits
865 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
503b8cbf34 | ||
![]() |
916356afad | ||
![]() |
41a84160ec | ||
![]() |
55f071e4a0 | ||
![]() |
0afe0f8fbd | ||
![]() |
427b5bd126 | ||
![]() |
20f6378a3e | ||
![]() |
36e0a1eb23 | ||
![]() |
ac9a567e1f | ||
![]() |
33cd52cddd | ||
![]() |
d543ba82ac | ||
![]() |
5a98993df9 | ||
![]() |
aee9c4a193 | ||
![]() |
0262f89bb0 | ||
![]() |
a8c530a3a9 | ||
![]() |
7dc1240c18 | ||
![]() |
3b4bccd0a7 | ||
![]() |
39a80f8dc7 | ||
![]() |
ce446dac92 | ||
![]() |
b1c9dbd0a5 | ||
![]() |
a5c57d7fb0 | ||
![]() |
0a349e5298 | ||
![]() |
dc7d7150cd | ||
![]() |
7c4aa4441f | ||
![]() |
62a795bd3b | ||
![]() |
c583ab4f1a | ||
![]() |
45a2970307 | ||
![]() |
5a4b719995 | ||
![]() |
34a4a89bc9 | ||
![]() |
02989f65ff | ||
![]() |
1da539ef05 | ||
![]() |
38d6fbd3d3 | ||
![]() |
39682a4cf1 | ||
![]() |
993a5805cd | ||
![]() |
09cf528cc6 | ||
![]() |
18ab2b3ab5 | ||
![]() |
655fbf91e2 | ||
![]() |
980794ea43 | ||
![]() |
c1cab30daf | ||
![]() |
b50e798d55 | ||
![]() |
230e3ef842 | ||
![]() |
2635a3edd0 | ||
![]() |
47f24ac151 | ||
![]() |
42397a01bf | ||
![]() |
7730a00dbb | ||
![]() |
3a4f4c8c34 | ||
![]() |
a0d88b0cbe | ||
![]() |
bb0419837b | ||
![]() |
35098c474c | ||
![]() |
0ca6535345 | ||
![]() |
ec6a243e3e | ||
![]() |
2cd8ee4a13 | ||
![]() |
432755e05d | ||
![]() |
51a7c2adc5 | ||
![]() |
5c1f793887 | ||
![]() |
e5dc473ced | ||
![]() |
e57a518b34 | ||
![]() |
533f86c035 | ||
![]() |
9947c51af7 | ||
![]() |
409303d0f5 | ||
![]() |
10a1275a52 | ||
![]() |
5464cbc2ed | ||
![]() |
3b3f8e6f43 | ||
![]() |
2d4d7bf937 | ||
![]() |
652651668f | ||
![]() |
e57d5d86f3 | ||
![]() |
4f7dc5be34 | ||
![]() |
b2c656940b | ||
![]() |
f8266d9811 | ||
![]() |
5c03550a8a | ||
![]() |
ed5491a480 | ||
![]() |
e8371f403b | ||
![]() |
373cffb261 | ||
![]() |
2bf22766eb | ||
![]() |
83530fcaf1 | ||
![]() |
6a41123209 | ||
![]() |
c895c5c16e | ||
![]() |
9ab4b3f3f4 | ||
![]() |
b93dd47a01 | ||
![]() |
69a826f896 | ||
![]() |
60c7ec5aca | ||
![]() |
888eacb574 | ||
![]() |
4def582ab1 | ||
![]() |
ee6f25cc47 | ||
![]() |
f5d6383f50 | ||
![]() |
00f00b8198 | ||
![]() |
3d1f883465 | ||
![]() |
8613a89931 | ||
![]() |
dd1485a66a | ||
![]() |
4198954d46 | ||
![]() |
e56caa8959 | ||
![]() |
de7c72d5a7 | ||
![]() |
18a4a43f8a | ||
![]() |
70c73d2e0e | ||
![]() |
2049e8b8df | ||
![]() |
41da889a09 | ||
![]() |
0a1bbca321 | ||
![]() |
7e01d113d8 | ||
![]() |
6e49cc54ac | ||
![]() |
487a95eb79 | ||
![]() |
696e438df7 | ||
![]() |
a4e093159e | ||
![]() |
23986579bb | ||
![]() |
0fc099926f | ||
![]() |
06b9b66272 | ||
![]() |
fec8343f45 | ||
![]() |
2d8f2593f0 | ||
![]() |
ab0a03a420 | ||
![]() |
3ef30a42be | ||
![]() |
034687163f | ||
![]() |
190db80c28 | ||
![]() |
579f355852 | ||
![]() |
d9104433a8 | ||
![]() |
c6059f9bf6 | ||
![]() |
fd06ff08c7 | ||
![]() |
afd990bd71 | ||
![]() |
8333c4b48d | ||
![]() |
30c4f501fc | ||
![]() |
3b96eef2ad | ||
![]() |
a769ab6cff | ||
![]() |
ef1f835e57 | ||
![]() |
329b2ba275 | ||
![]() |
98383ef19b | ||
![]() |
72cca365e5 | ||
![]() |
71886c162b | ||
![]() |
df1f516f6b | ||
![]() |
2e55189d59 | ||
![]() |
6ade40ce85 | ||
![]() |
94c5f0d7a8 | ||
![]() |
69a2ac8de1 | ||
![]() |
b1028086a3 | ||
![]() |
385b3570b2 | ||
![]() |
77edd12030 | ||
![]() |
217fca31e4 | ||
![]() |
5e1d20fc72 | ||
![]() |
db60309ce8 | ||
![]() |
8bfae2fa74 | ||
![]() |
2788dd1ada | ||
![]() |
6a5b757a24 | ||
![]() |
a19098a004 | ||
![]() |
ec10c29aca | ||
![]() |
f90ab46794 | ||
![]() |
b8ca97e019 | ||
![]() |
e12757dbb9 | ||
![]() |
3e9b44d193 | ||
![]() |
3006d25406 | ||
![]() |
f2ae9a0711 | ||
![]() |
19945e4ccb | ||
![]() |
61ab16acd6 | ||
![]() |
3a84292f82 | ||
![]() |
1d314294c7 | ||
![]() |
b5b1dbfe85 | ||
![]() |
5be88dd188 | ||
![]() |
88b67b9541 | ||
![]() |
a31da3186f | ||
![]() |
9a7a38e913 | ||
![]() |
a0960f5468 | ||
![]() |
9b87a512cf | ||
![]() |
8da985b6d0 | ||
![]() |
5cb2a39746 | ||
![]() |
6268cadc95 | ||
![]() |
470b4b3972 | ||
![]() |
a88ae2ca56 | ||
![]() |
9875fbef0a | ||
![]() |
cf29ddc8d0 | ||
![]() |
ad70fcba7f | ||
![]() |
a9a7720a11 | ||
![]() |
8ff4f50f79 | ||
![]() |
aea07f42d1 | ||
![]() |
8d75c06852 | ||
![]() |
ffbedbc1e6 | ||
![]() |
a47d48c973 | ||
![]() |
c54092c932 | ||
![]() |
9134c3b4af | ||
![]() |
7e21955211 | ||
![]() |
40ac760285 | ||
![]() |
de63bdac39 | ||
![]() |
408d63825a | ||
![]() |
3e1eb02f54 | ||
![]() |
d2f55e1064 | ||
![]() |
c97bead631 | ||
![]() |
8264ca4e9e | ||
![]() |
05bdaa4bc7 | ||
![]() |
cc2de04f6b | ||
![]() |
f99f13a090 | ||
![]() |
f35ab125ec | ||
![]() |
b8342f1c9c | ||
![]() |
0ce77bbc59 | ||
![]() |
e39eccb99e | ||
![]() |
77ce67d685 | ||
![]() |
ef125ff109 | ||
![]() |
30e3bbd0e8 | ||
![]() |
7bf1c35dcf | ||
![]() |
c6ea2dff8a | ||
![]() |
f2329476ec | ||
![]() |
c4512b75d9 | ||
![]() |
92e43abbc4 | ||
![]() |
07d6bfa989 | ||
![]() |
ccf5e66f31 | ||
![]() |
6f5e71164a | ||
![]() |
12131764d1 | ||
![]() |
594c0b8550 | ||
![]() |
ed729c32d2 | ||
![]() |
ea26ee8d40 | ||
![]() |
53f09c0630 | ||
![]() |
2856e02eac | ||
![]() |
a4f0c9195e | ||
![]() |
0e73a0293b | ||
![]() |
f4f5d6e562 | ||
![]() |
e5c3629e2e | ||
![]() |
5028471598 | ||
![]() |
c28027496d | ||
![]() |
c0f5509652 | ||
![]() |
9bc48ececa | ||
![]() |
1f53e4d4a2 | ||
![]() |
dbef0e6583 | ||
![]() |
c246e5af35 | ||
![]() |
d36796429e | ||
![]() |
37a31a9b94 | ||
![]() |
c2ab3f96a7 | ||
![]() |
ef36b5377d | ||
![]() |
f12237d298 | ||
![]() |
5b312d4c8b | ||
![]() |
d21e82b020 | ||
![]() |
c6e5606b4c | ||
![]() |
7b4dc43147 | ||
![]() |
62510ac6a3 | ||
![]() |
bffe2d7bd0 | ||
![]() |
cbaf1e576d | ||
![]() |
0d355dbf35 | ||
![]() |
d851bff762 | ||
![]() |
453f4b549b | ||
![]() |
8d669b12b6 | ||
![]() |
ed3234d949 | ||
![]() |
603a00376f | ||
![]() |
4f34cfb654 | ||
![]() |
fd1e536cdb | ||
![]() |
0c6a880a74 | ||
![]() |
89fa053310 | ||
![]() |
267887908e | ||
![]() |
b86f58befe | ||
![]() |
b804101c24 | ||
![]() |
f28502514f | ||
![]() |
79da716a44 | ||
![]() |
f76a440b74 | ||
![]() |
18dad0c72c | ||
![]() |
14a5ab6740 | ||
![]() |
d0d56c4416 | ||
![]() |
9dd9a01211 | ||
![]() |
480e7f5b54 | ||
![]() |
cffee7bfa7 | ||
![]() |
5b9eda9c63 | ||
![]() |
0a363d5fc0 | ||
![]() |
9eb646085e | ||
![]() |
e3269f6edc | ||
![]() |
57d3120b45 | ||
![]() |
81da8261a0 | ||
![]() |
7e5949b4a9 | ||
![]() |
a776b8ac31 | ||
![]() |
14e19226ea | ||
![]() |
5473b3e42e | ||
![]() |
143179cac9 | ||
![]() |
ad2c7ee363 | ||
![]() |
755448f9f5 | ||
![]() |
f304a6891f | ||
![]() |
1221661ae3 | ||
![]() |
a78f17abec | ||
![]() |
70bf957a8a | ||
![]() |
e8e04db7b4 | ||
![]() |
d5def30c59 | ||
![]() |
81176bc4e6 | ||
![]() |
730ba12c8d | ||
![]() |
80ad456d48 | ||
![]() |
2d75526395 | ||
![]() |
cd618a43d4 | ||
![]() |
1979236f3a | ||
![]() |
3589adcb78 | ||
![]() |
4a834ecfc8 | ||
![]() |
3dcc3492e8 | ||
![]() |
2e77dcc660 | ||
![]() |
89f60a0422 | ||
![]() |
0455c09e4c | ||
![]() |
7360b882ac | ||
![]() |
5ffd29e31a | ||
![]() |
5d7e892464 | ||
![]() |
e8fd5de5b2 | ||
![]() |
a8e7aa99e8 | ||
![]() |
9a0db83f83 | ||
![]() |
4e85566b88 | ||
![]() |
8be72f6f23 | ||
![]() |
513bc2c0ab | ||
![]() |
036ba77a68 | ||
![]() |
392277100c | ||
![]() |
a7092ac503 | ||
![]() |
027a16a39b | ||
![]() |
c66af86d88 | ||
![]() |
e621fdec0c | ||
![]() |
447594b5ea | ||
![]() |
a0b208cca0 | ||
![]() |
1a4061fdb5 | ||
![]() |
fb59f1f0a0 | ||
![]() |
b1961033b3 | ||
![]() |
863498f762 | ||
![]() |
bdc44a4070 | ||
![]() |
6451522f89 | ||
![]() |
5ca1e9268c | ||
![]() |
451a6841c9 | ||
![]() |
3e3f46a683 | ||
![]() |
2b0eaafea6 | ||
![]() |
c1a8fde9a0 | ||
![]() |
9dbd1b2a1b | ||
![]() |
0cc1007543 | ||
![]() |
8ca86181e4 | ||
![]() |
8759d8f868 | ||
![]() |
65a32b4166 | ||
![]() |
933a0cddf8 | ||
![]() |
d4c0542c84 | ||
![]() |
05f5aaaeca | ||
![]() |
036bd07e72 | ||
![]() |
9c3e7b9ec0 | ||
![]() |
1fd0383f69 | ||
![]() |
9e62db5237 | ||
![]() |
3062786bb3 | ||
![]() |
b42847c135 | ||
![]() |
5befcd24b5 | ||
![]() |
61f3002568 | ||
![]() |
0b7e0e166c | ||
![]() |
3b52770a1b | ||
![]() |
d0b9f53d8c | ||
![]() |
92a9d7d26a | ||
![]() |
ffd958a1b3 | ||
![]() |
a7e9c7e24b | ||
![]() |
9839cc6386 | ||
![]() |
8d66d38fd2 | ||
![]() |
a004d1647d | ||
![]() |
21fe2c5f8f | ||
![]() |
867e43637c | ||
![]() |
c9025917b2 | ||
![]() |
258def854c | ||
![]() |
e8481818c8 | ||
![]() |
f646e9bc59 | ||
![]() |
680923bdd5 | ||
![]() |
17e43a7ff2 | ||
![]() |
71a5cfed4b | ||
![]() |
c055477d3b | ||
![]() |
ad4acca17a | ||
![]() |
37b84300b4 | ||
![]() |
d9a8dac266 | ||
![]() |
76f704b060 | ||
![]() |
cde360f7ec | ||
![]() |
d69a2f1514 | ||
![]() |
06a5c1a798 | ||
![]() |
ca1f25ecf6 | ||
![]() |
adcd7fb170 | ||
![]() |
f105436b41 | ||
![]() |
47738c751c | ||
![]() |
0b3f2da6ef | ||
![]() |
fa7092cc17 | ||
![]() |
773d6e002c | ||
![]() |
b78d1baaaf | ||
![]() |
50ff59239c | ||
![]() |
8f36878dde | ||
![]() |
a29e98fd41 | ||
![]() |
e4d5551f16 | ||
![]() |
e610a1ffe4 | ||
![]() |
ac927d188b | ||
![]() |
bbf2f6c7de | ||
![]() |
398816dbeb | ||
![]() |
f3b399b31f | ||
![]() |
2b0a38d25d | ||
![]() |
b41dacb6c0 | ||
![]() |
c5f5532303 | ||
![]() |
09485c995e | ||
![]() |
dc936b63d6 | ||
![]() |
b5213794a8 | ||
![]() |
2f8365a790 | ||
![]() |
47be430bc1 | ||
![]() |
918da24c8d | ||
![]() |
0e82f2a02f | ||
![]() |
447f15cfa4 | ||
![]() |
8f80c206e7 | ||
![]() |
e1a61985a2 | ||
![]() |
16ad0c22f0 | ||
![]() |
3d0d027216 | ||
![]() |
b58a17a99e | ||
![]() |
adaf2e15cd | ||
![]() |
1723683370 | ||
![]() |
9cd0a7982a | ||
![]() |
d2726aae90 | ||
![]() |
607a66b983 | ||
![]() |
38b2adcaad | ||
![]() |
d7879d8853 | ||
![]() |
2d5b09a16f | ||
![]() |
a06a722c23 | ||
![]() |
d9d45f86cb | ||
![]() |
e49b9cff67 | ||
![]() |
8c69a4cb7a | ||
![]() |
1042ac141a | ||
![]() |
81aab35231 | ||
![]() |
1c5742c7d4 | ||
![]() |
4d646e67f3 | ||
![]() |
59fbc51283 | ||
![]() |
125e21900a | ||
![]() |
569efd3e45 | ||
![]() |
6c557ec015 | ||
![]() |
63b917eb07 | ||
![]() |
71af63dfc7 | ||
![]() |
0cae048ada | ||
![]() |
71021da261 | ||
![]() |
1d897e491a | ||
![]() |
57c0b408e5 | ||
![]() |
43e0186efe | ||
![]() |
8831d74cbc | ||
![]() |
9a9d2cb964 | ||
![]() |
2fc2a0cbdb | ||
![]() |
40c041c9e7 | ||
![]() |
b00c1dd055 | ||
![]() |
761245049f | ||
![]() |
30e142edd3 | ||
![]() |
b7d84c002d | ||
![]() |
551afe0cd7 | ||
![]() |
5d8bfc2930 | ||
![]() |
5d947cc8e1 | ||
![]() |
7bf92db4c9 | ||
![]() |
593c1d6b05 | ||
![]() |
30e326b8b8 | ||
![]() |
cf60eb52d8 | ||
![]() |
8850dac291 | ||
![]() |
bed52d0a4a | ||
![]() |
10e564eeea | ||
![]() |
ae47c4c79a | ||
![]() |
8048bb85fb | ||
![]() |
e99e9fed11 | ||
![]() |
79e9dbb9c6 | ||
![]() |
081a6888fa | ||
![]() |
ae6ba79f1e | ||
![]() |
d9d2ad4382 | ||
![]() |
31d277ffa2 | ||
![]() |
7fe5f8907e | ||
![]() |
2e9b59e2e0 | ||
![]() |
5188894301 | ||
![]() |
4c16efbbf7 | ||
![]() |
8055243909 | ||
![]() |
2eb4383e03 | ||
![]() |
bafd043aae | ||
![]() |
3379e7cc48 | ||
![]() |
d971fc440f | ||
![]() |
31658f4eab | ||
![]() |
339be2b7a4 | ||
![]() |
3e716e429f | ||
![]() |
a8a61665f4 | ||
![]() |
a7a1002509 | ||
![]() |
65154e48cb | ||
![]() |
32c10e5ae8 | ||
![]() |
61ee1c6ff3 | ||
![]() |
6642d96688 | ||
![]() |
df8b085f0e | ||
![]() |
7a415ccdfc | ||
![]() |
2a432dc6ee | ||
![]() |
322d1f09de | ||
![]() |
44f4bd6e62 | ||
![]() |
2bb74233cc | ||
![]() |
19f6fd2295 | ||
![]() |
558811e4f9 | ||
![]() |
ed560a338e | ||
![]() |
74741682bf | ||
![]() |
d32d4e21e9 | ||
![]() |
78f301d503 | ||
![]() |
318ffc821c | ||
![]() |
ef4ec16860 | ||
![]() |
6bc927c535 | ||
![]() |
2fe2b3c975 | ||
![]() |
e4ad0d3b59 | ||
![]() |
750261d205 | ||
![]() |
df1b25f381 | ||
![]() |
4af7ccd84c | ||
![]() |
4282053f68 | ||
![]() |
5c7d993dbe | ||
![]() |
cdef7a53a4 | ||
![]() |
b1f26d4ebe | ||
![]() |
9bf534288c | ||
![]() |
3d359229cf | ||
![]() |
8013f8d5b3 | ||
![]() |
cf12ab4b74 | ||
![]() |
0f3eecaa8a | ||
![]() |
22c1f4bb4e | ||
![]() |
43c5fea782 | ||
![]() |
41eab27f20 | ||
![]() |
ba354f68d1 | ||
![]() |
a6c7cc7b41 | ||
![]() |
4dfc1631af | ||
![]() |
58861fa524 | ||
![]() |
1c6b1c530f | ||
![]() |
21b498fece | ||
![]() |
446e2c123f | ||
![]() |
b3a7ee633d | ||
![]() |
8b6366688a | ||
![]() |
1671c78260 | ||
![]() |
96ca459df8 | ||
![]() |
51fb981d24 | ||
![]() |
2ef46195d3 | ||
![]() |
6e35b5ba8b | ||
![]() |
b8ea0bd1ff | ||
![]() |
8ca6ca2c88 | ||
![]() |
508804d0d5 | ||
![]() |
eb251050a5 | ||
![]() |
67758b4980 | ||
![]() |
f187d7258b | ||
![]() |
5efd1f3a91 | ||
![]() |
e3def22b07 | ||
![]() |
ce5839ce27 | ||
![]() |
50082043ef | ||
![]() |
012045878d | ||
![]() |
3083ccddcc | ||
![]() |
f39b9041a0 | ||
![]() |
37827cdd6c | ||
![]() |
58f41a1f9b | ||
![]() |
7712faca0a | ||
![]() |
805fe1d47e | ||
![]() |
0d4d1eff94 | ||
![]() |
38cc460358 | ||
![]() |
8600360173 | ||
![]() |
f3371c443e | ||
![]() |
a86f750473 | ||
![]() |
92b532ce9a | ||
![]() |
924f97cbe8 | ||
![]() |
8817dc6d73 | ||
![]() |
7324d59e08 | ||
![]() |
dcd8e9250f | ||
![]() |
f07578e0cb | ||
![]() |
cabcf8b7b2 | ||
![]() |
a90a07f46d | ||
![]() |
9839bab8dc | ||
![]() |
b9dd3de63b | ||
![]() |
194aa90aee | ||
![]() |
9bc72df1b5 | ||
![]() |
b2439ca0af | ||
![]() |
70d04d807b | ||
![]() |
2372675c79 | ||
![]() |
cb66900575 | ||
![]() |
de4be44728 | ||
![]() |
21dc037848 | ||
![]() |
9fe5e69503 | ||
![]() |
c0ac381f6f | ||
![]() |
5f235c121d | ||
![]() |
6b8e9a63f3 | ||
![]() |
3dcda08735 | ||
![]() |
f92ee8e762 | ||
![]() |
94200dd3a4 | ||
![]() |
512c4dd6f1 | ||
![]() |
6d43854557 | ||
![]() |
112ba7ac5c | ||
![]() |
4c58929dd4 | ||
![]() |
2188509d2c | ||
![]() |
263ef14822 | ||
![]() |
ed24f72cf9 | ||
![]() |
c1197d06fe | ||
![]() |
bd4d1cdd41 | ||
![]() |
2c70d66d4a | ||
![]() |
97ecace40e | ||
![]() |
6ef988549d | ||
![]() |
9088d79390 | ||
![]() |
0c9bcb2445 | ||
![]() |
c98c54bd6b | ||
![]() |
225e66a522 | ||
![]() |
f1810a9784 | ||
![]() |
9526051766 | ||
![]() |
bd435b175b | ||
![]() |
42ab734256 | ||
![]() |
77d89e7df3 | ||
![]() |
c1dec16c50 | ||
![]() |
86ae11f4c4 | ||
![]() |
7ca1970fff | ||
![]() |
b1cbbeb935 | ||
![]() |
2dce4462a0 | ||
![]() |
55e2bc27c6 | ||
![]() |
2c3cad6e61 | ||
![]() |
6122a8371a | ||
![]() |
4ffeb05120 | ||
![]() |
310f55abb6 | ||
![]() |
d6c0642a02 | ||
![]() |
541556874f | ||
![]() |
477d7080b8 | ||
![]() |
173c752d62 | ||
![]() |
3b70488828 | ||
![]() |
334783f89a | ||
![]() |
89a54e31f1 | ||
![]() |
354d18f78e | ||
![]() |
0e8806eb2b | ||
![]() |
731550acb3 | ||
![]() |
be4019b4d3 | ||
![]() |
70ffcd9adf | ||
![]() |
bbe511dd15 | ||
![]() |
82d5ac91d7 | ||
![]() |
54de0eab6a | ||
![]() |
4d5bb274d1 | ||
![]() |
131fae57e5 | ||
![]() |
37da53c20e | ||
![]() |
6ad57a15cf | ||
![]() |
4729bce16c | ||
![]() |
0b5ac7a139 | ||
![]() |
677e23ad14 | ||
![]() |
6d838e3043 | ||
![]() |
f322abceb8 | ||
![]() |
e754d21598 | ||
![]() |
0fdd861ef1 | ||
![]() |
2e5f6a3507 | ||
![]() |
4e57cab0fa | ||
![]() |
9930c8f94d | ||
![]() |
f8e262b87e | ||
![]() |
896bdaf124 | ||
![]() |
2e4f2639a3 | ||
![]() |
ce89a92d0d | ||
![]() |
1d9d1f6bbd | ||
![]() |
767b57fc01 | ||
![]() |
9e00177d76 | ||
![]() |
095429a7df | ||
![]() |
983efd61fb | ||
![]() |
e028316308 | ||
![]() |
e1354accb8 | ||
![]() |
ea726f928d | ||
![]() |
6b419dbfc0 | ||
![]() |
006a9eaf44 | ||
![]() |
76117854c6 | ||
![]() |
6eae6db46b | ||
![]() |
3aacb7150d | ||
![]() |
81298a1034 | ||
![]() |
b3d728df91 | ||
![]() |
9a091ff11a | ||
![]() |
6989b1730e | ||
![]() |
1595542d59 | ||
![]() |
fba9992a10 | ||
![]() |
867dce2294 | ||
![]() |
692554a899 | ||
![]() |
f3cc616e07 | ||
![]() |
d1c289b709 | ||
![]() |
e7a0874a57 | ||
![]() |
1beb9c4bb8 | ||
![]() |
6eef3a9037 | ||
![]() |
ddaaae46a6 | ||
![]() |
4e4773a370 | ||
![]() |
f4a2ffc5d2 | ||
![]() |
ba1117e10e | ||
![]() |
0cd46f932a | ||
![]() |
937f404583 | ||
![]() |
d13d60d752 | ||
![]() |
31e4e7c709 | ||
![]() |
0d3a8ce31b | ||
![]() |
be185b46a7 | ||
![]() |
90fa5b3b93 | ||
![]() |
733996772b | ||
![]() |
d4c921ea2e | ||
![]() |
2852061699 | ||
![]() |
d8859b9f0a | ||
![]() |
ae1bc96006 | ||
![]() |
f30ffb4413 | ||
![]() |
273c6467c8 | ||
![]() |
846a1d007c | ||
![]() |
1dccc8dc78 | ||
![]() |
e0d67bd057 | ||
![]() |
4b4b93ac04 | ||
![]() |
4390aee1e0 | ||
![]() |
4cddb16788 | ||
![]() |
e1179fd8c8 | ||
![]() |
cb77285277 | ||
![]() |
6c9d161950 | ||
![]() |
40aaac5868 | ||
![]() |
e16b69594e | ||
![]() |
4837bf007a | ||
![]() |
705fd4dafd | ||
![]() |
a3e28d3c66 | ||
![]() |
4a6755c28a | ||
![]() |
188fe5dc52 | ||
![]() |
44a8ae457d | ||
![]() |
92eafcfe1a | ||
![]() |
b12b031fdd | ||
![]() |
492ec489a1 | ||
![]() |
c57124e876 | ||
![]() |
95b33c9c34 | ||
![]() |
c6d8b63e54 | ||
![]() |
f0f02c4ea6 | ||
![]() |
eb2cb6810a | ||
![]() |
b3c090e9ed | ||
![]() |
13366fc9f8 | ||
![]() |
929af7830a | ||
![]() |
13062cf0e4 | ||
![]() |
b897a8a35f | ||
![]() |
117dc5288d | ||
![]() |
4b5a3bd3d5 | ||
![]() |
b224a67ea7 | ||
![]() |
793f919d59 | ||
![]() |
315987b2f6 | ||
![]() |
9b7db548a2 | ||
![]() |
126b70f781 | ||
![]() |
0bbff627e2 | ||
![]() |
961d23e2a1 | ||
![]() |
b03ff9a48a | ||
![]() |
3ffb40fafa | ||
![]() |
1a3b4ac2ac | ||
![]() |
794e17442f | ||
![]() |
238d7119e0 | ||
![]() |
8a929a8348 | ||
![]() |
cf77153647 | ||
![]() |
a2da0b0641 | ||
![]() |
73faa13811 | ||
![]() |
1a71872c7b | ||
![]() |
62fe7135bd | ||
![]() |
078940d29f | ||
![]() |
2fafe42c18 | ||
![]() |
c8a7537157 | ||
![]() |
d4bf1cb23d | ||
![]() |
46e4350013 | ||
![]() |
202eb0d854 | ||
![]() |
898702346e | ||
![]() |
b72e6f16ca | ||
![]() |
b9c27ed324 | ||
![]() |
0166dfe16e | ||
![]() |
7274541722 | ||
![]() |
709ff7a701 | ||
![]() |
66c224c954 | ||
![]() |
3f9b37aa7f | ||
![]() |
0377958d8f | ||
![]() |
cc1cfd70b8 | ||
![]() |
bc125ad76c | ||
![]() |
62a2246448 | ||
![]() |
587cf751d8 | ||
![]() |
600181ed07 | ||
![]() |
f0e525d2e2 | ||
![]() |
f86cdd8cde | ||
![]() |
4a4c537a0d | ||
![]() |
1caaf04dfa | ||
![]() |
b422a80249 | ||
![]() |
ba19e20833 | ||
![]() |
c34ddb2bc3 | ||
![]() |
aa315f8472 | ||
![]() |
2af6af2bf0 | ||
![]() |
5694ff7c97 | ||
![]() |
76f1c689c1 | ||
![]() |
a371239172 | ||
![]() |
4fd904fbcc | ||
![]() |
b73a257389 | ||
![]() |
9e70d6b3e1 | ||
![]() |
9caca37ab1 | ||
![]() |
6e76fc0aa7 | ||
![]() |
6171883758 | ||
![]() |
942b68c948 | ||
![]() |
9ca7ffa5a3 | ||
![]() |
d1ce23c5ac | ||
![]() |
b7b6d0a6bc | ||
![]() |
10c51eea2c | ||
![]() |
48d20c02a1 | ||
![]() |
c5cc0b3f2b | ||
![]() |
6ebef8846c | ||
![]() |
5d1993935e | ||
![]() |
caab8943cb | ||
![]() |
f5c05b24fb | ||
![]() |
940a0d006d | ||
![]() |
8fe67a04d8 | ||
![]() |
bec745d095 | ||
![]() |
223fd35138 | ||
![]() |
d3fc0309c0 | ||
![]() |
830223f6e2 | ||
![]() |
eb53c52499 | ||
![]() |
96c9e2b4d6 | ||
![]() |
c34b948bad | ||
![]() |
9ac609f846 | ||
![]() |
6aa47bfd1b | ||
![]() |
ff46e6ea86 | ||
![]() |
5489c74986 | ||
![]() |
f6f8151150 | ||
![]() |
a20d577f6c | ||
![]() |
c4c2494dd1 | ||
![]() |
c9c294a1d5 | ||
![]() |
6359a8a8a2 | ||
![]() |
f9b44381bd | ||
![]() |
eb1ccb600b | ||
![]() |
b2db61aa03 | ||
![]() |
ee55a574de | ||
![]() |
0998fd32cd | ||
![]() |
686f2c4aa6 | ||
![]() |
cd234673ea | ||
![]() |
54d7a81f16 | ||
![]() |
9d8d2c0aa1 | ||
![]() |
17ce6b9507 | ||
![]() |
296065a976 | ||
![]() |
0b0f600f97 | ||
![]() |
f1371d6737 | ||
![]() |
03a33790e1 | ||
![]() |
c0816c80ae | ||
![]() |
071ebe6ef2 | ||
![]() |
2126e42743 | ||
![]() |
8a2b34adb4 | ||
![]() |
93eb4d21bf | ||
![]() |
868cedeed2 | ||
![]() |
5c794f428a | ||
![]() |
612d6f85bd | ||
![]() |
e5cef6b877 | ||
![]() |
f2a63c04a8 | ||
![]() |
5a5064e070 | ||
![]() |
478fa3132c | ||
![]() |
a84859c211 | ||
![]() |
67013bd58f | ||
![]() |
b51be31d8a | ||
![]() |
a3bef49124 | ||
![]() |
a5cf553f17 | ||
![]() |
640188f4e2 | ||
![]() |
48265bbe02 | ||
![]() |
6aaf544079 | ||
![]() |
9904c10984 | ||
![]() |
81c810eba4 | ||
![]() |
5e6b1e8175 | ||
![]() |
48c165b0b4 | ||
![]() |
042605701e | ||
![]() |
32cf1495d3 | ||
![]() |
9577e49231 | ||
![]() |
de19839145 | ||
![]() |
f970780d6c | ||
![]() |
1e69cc75c7 | ||
![]() |
377e4fa0a5 | ||
![]() |
a5d6dc58d3 | ||
![]() |
a122c17340 | ||
![]() |
34ddf104a9 | ||
![]() |
f98b0beee5 | ||
![]() |
75a61f85db | ||
![]() |
c1cdf27507 | ||
![]() |
43e9743645 | ||
![]() |
c2972786f5 | ||
![]() |
eeb17b417c | ||
![]() |
473991638c | ||
![]() |
92b4b69b3f | ||
![]() |
dbd6f134c1 | ||
![]() |
5f59487a88 | ||
![]() |
bb7f673ff9 | ||
![]() |
4715180a32 | ||
![]() |
4b31610169 | ||
![]() |
2466c5a204 | ||
![]() |
0505baff38 | ||
![]() |
c55e3a37ae | ||
![]() |
ce5fec4d5f | ||
![]() |
6d4339b034 | ||
![]() |
70d0aae07c | ||
![]() |
e3b9b341fd | ||
![]() |
95083cf743 | ||
![]() |
3842c4ac46 | ||
![]() |
fe178043ee | ||
![]() |
82d40f60f1 | ||
![]() |
1d4d885276 | ||
![]() |
ed3557ffca | ||
![]() |
1c3878fcb0 | ||
![]() |
b3dcb9fe6c | ||
![]() |
0462755922 | ||
![]() |
415dfd2750 | ||
![]() |
72f203e4fa | ||
![]() |
4e3c83af94 | ||
![]() |
65a0f60257 | ||
![]() |
094bdf02c4 | ||
![]() |
5d8d12bc89 | ||
![]() |
89b9fd8a45 | ||
![]() |
ce1ba3bc2c | ||
![]() |
3afb499930 | ||
![]() |
356ff57005 | ||
![]() |
16ce67057d | ||
![]() |
4c9dc739ae | ||
![]() |
a665607fac | ||
![]() |
7f5671f975 |
27
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug
|
||||
about: Noticed an issue with your lights?
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is. Please quickly search existing issues first!
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior, if consistently possible
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**WLED version**
|
||||
- Board: [e.g. Wemos D1, ESP32 dev]
|
||||
- Version [e.g. 0.10.0, dev200603]
|
||||
- Format [e.g. Binary, self-compiled]
|
||||
|
||||
**Additional context**
|
||||
Anything else you'd like to say about the problem?
|
||||
|
||||
Thank you for your help!
|
22
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an improvement idea for WLED!
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
Thank you for your ideas for making WLED better!
|
19
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Question
|
||||
about: Have a question about using WLED?
|
||||
title: ''
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Take a look at the wiki and FAQ, perhaps your question is already answered!**
|
||||
[FAQ](https://github.com/Aircoookie/WLED/wiki/FAQ)
|
||||
|
||||
**Please consider asking your question on the WLED forum or Discord**
|
||||
[Forum](https://wled.discourse.group/)
|
||||
[Discord](https://discord.gg/KuqP7NE)
|
||||
[What to post where?](https://github.com/Aircoookie/WLED/issues/658)
|
||||
|
||||
**If you do not like to use these platforms, delete this template and ask away!**
|
||||
Please keep in mind though that the issue section is generally not the preferred place for general questions.
|
20
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 120
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- keep
|
||||
- enhancement
|
||||
- confirmed
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Hey! This issue has been open for quite some time without any new comments now.
|
||||
It will be closed automatically in a week if no further activity occurs.
|
||||
|
||||
Thank you for using WLED!
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
.pio
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.vscode
|
||||
!.vscode/extensions.json
|
||||
/wled00/Release
|
||||
/wled00/extLibs
|
||||
/platformio_override.ini
|
||||
.DS_Store
|
||||
.gitignore
|
||||
.clang-format
|
||||
node_modules
|
43
.travis.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
# Continuous Integration (CI) is the practice, in software
|
||||
# engineering, of merging all developer working copies with a shared mainline
|
||||
# several times a day < https://docs.platformio.org/page/ci/index.html >
|
||||
#
|
||||
# Documentation:
|
||||
#
|
||||
# * Travis CI Embedded Builds with PlatformIO
|
||||
# < https://docs.travis-ci.com/user/integration/platformio/ >
|
||||
#
|
||||
# * PlatformIO integration with Travis CI
|
||||
# < https://docs.platformio.org/page/ci/travis.html >
|
||||
#
|
||||
# * User Guide for `platformio ci` command
|
||||
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
|
||||
#
|
||||
#
|
||||
# Please choose one of the following templates (proposed below) and uncomment
|
||||
# it (remove "# " before each line) or use own configuration according to the
|
||||
# Travis CI documentation (see above).
|
||||
#
|
||||
# * Test the Travis config here:
|
||||
# < https://config.travis-ci.com/explore >
|
||||
#
|
||||
|
||||
language: python
|
||||
python:
|
||||
# - "2.7"
|
||||
- "3.5"
|
||||
os: linux
|
||||
cache:
|
||||
bundler: true
|
||||
ccache: true
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "~/.buildcache"
|
||||
env:
|
||||
- PLATFORMIO_CI_SRC=wled00
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- platformio update
|
||||
script:
|
||||
# - platformio ci --project-conf=./platformio.ini
|
||||
- platformio run
|
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
228
CHANGELOG.md
Normal file
@@ -0,0 +1,228 @@
|
||||
## WLED changelog
|
||||
|
||||
### WLED version 0.10.2
|
||||
|
||||
#### Build 2008310
|
||||
|
||||
- Added new logo
|
||||
- Maximum GZIP compression (#1126)
|
||||
- Enable WebSockets by default
|
||||
|
||||
### Development versions between 0.10.0 and 0.10.2 releases
|
||||
|
||||
#### Build 2008300
|
||||
|
||||
- Added new UI customization options to UI settings
|
||||
- Added Dancing Shadows effect (#1108)
|
||||
- Preset cycle is now paused if lights turned off or nightlight active
|
||||
- Removed `esp01` and `esp01_ota` envs from travis build (need too much flash)
|
||||
|
||||
#### Build 2008290
|
||||
|
||||
- Added individual LED control support to JSON API
|
||||
- Added internal Segment Freeze/Pause option
|
||||
|
||||
#### Build 2008250
|
||||
|
||||
- Made `platformio_override.ini` example easier to use by including the `default_envs` property
|
||||
- FastLED uses `now` as timer, so effects using e.g. `beatsin88()` will sync correctly
|
||||
- Extended the speed range of Pacifica effect
|
||||
- Improved TPM2.net receiving (#1100)
|
||||
- Fixed exception on empty MQTT payload (#1101)
|
||||
|
||||
#### Build 2008200
|
||||
|
||||
- Added segment mirroring to web UI
|
||||
- Fixed segment mirroring when in reverse mode
|
||||
|
||||
#### Build 2008140
|
||||
|
||||
- Removed verbose live mode info from `<ds>` in HTTP API response
|
||||
|
||||
#### Build 2008100
|
||||
|
||||
- Fixed Auto White mode setting (fixes #1088)
|
||||
|
||||
#### Build 2008070
|
||||
|
||||
- Added segment mirroring (`mi` property) (#1017)
|
||||
- Fixed DMX settings page not displayed (#1070)
|
||||
- Fixed ArtNet multi universe and improve code style (#1076)
|
||||
- Renamed global var `local` to `localTime` (#1078)
|
||||
|
||||
#### Build 2007190
|
||||
|
||||
- Fixed hostname containing illegal characters (#1035)
|
||||
|
||||
#### Build 2006251
|
||||
|
||||
- Added `SV=2` to HTTP API, allow selecting single segment only
|
||||
|
||||
#### Build 2006250
|
||||
|
||||
- Fix Alexa not turning off white channel (fixes #1012)
|
||||
|
||||
#### Build 2006220
|
||||
|
||||
- Added Sunrise nightlight mode
|
||||
- Added Chunchun effect
|
||||
- Added `LO` (live override) command to HTTP API
|
||||
- Added `mode` to `nl` object of JSON state API, deprecating `fade`
|
||||
- Added light color scheme support to web UI (click sun next to brightness slider)
|
||||
- Added option to hide labels in web UI (click flame icon next to intensity slider)
|
||||
- Added hex color input (click palette icon next to palette select) (resolves #506)
|
||||
- Added support for RGB sliders (need to set in localstorage)
|
||||
- Added support for custom background color or image (need to set in localstorage)
|
||||
- Added option to hide bottom tab bar in PC mode (need to set in localstorage)
|
||||
- Fixed transition lag with multiple segments (fixes #985)
|
||||
- Changed Nightlight wording (resolves #940)
|
||||
|
||||
#### Build 2006060
|
||||
|
||||
- Added five effects by Andrew Tuline (Phased, Phased Noise, Sine, Noise Pal and Twinkleup)
|
||||
- Added two new effects by Aircoookie (Sunrise and Flow)
|
||||
- Added US-style sequence to traffic light effect
|
||||
- Merged pull request #964 adding 9 key IR remote
|
||||
|
||||
#### Build 2005280
|
||||
|
||||
- Added v2 usermod API
|
||||
- Added v2 example usermod `usermod_v2_example` in the usermods folder as prelimary documentation
|
||||
- Added DS18B20 Temperature usermod with Info page support
|
||||
- Disabled MQTT on ESP01 build to make room in flash
|
||||
|
||||
#### Build 2005230
|
||||
|
||||
- Fixed TPM2
|
||||
|
||||
#### Build 2005220
|
||||
|
||||
- Added TPM2.NET protocol support (need to set WLED broadcast UDP port to 65506)
|
||||
- Added TPM2 protocol support via Serial
|
||||
- Support up to 6553 seconds preset cycle durations (backend, NOT yet in UI)
|
||||
- Merged pull request #591 fixing WS2801 color order
|
||||
- Merged pull request #858 adding fully featured travis builds
|
||||
- Merged pull request #862 adding DMX proxy feature
|
||||
|
||||
#### Build 2005100
|
||||
|
||||
- Update to Espalexa v2.4.6 (+1.6kB free heap memory)
|
||||
- Added `m5atom` PlatformIO environment
|
||||
|
||||
#### Build 2005090
|
||||
|
||||
- Default to ESP8266 Arduino core v2.7.1 in PlatformIO
|
||||
- Fixed Preset Slot 16 always indicating as empty (#891)
|
||||
- Disabled Alexa emulation by default (causes bootloop for some users)
|
||||
- Added BWLT11 and SHOJO_PCB defines to NpbWrapper
|
||||
- Merged pull request #898 adding Solid Glitter effect
|
||||
|
||||
### WLED version 0.10.0
|
||||
|
||||
#### Build 2005030
|
||||
|
||||
- DMX Single RGW and Single DRGB modes now support an additional white channel
|
||||
- Improved palettes derived from set colors and changed their names
|
||||
|
||||
### Development versions between 0.9.1 and 0.10.0 release
|
||||
|
||||
#### Build 2005020
|
||||
|
||||
- Added ACST and ACST/ACDT timezones
|
||||
|
||||
#### Build 2005010
|
||||
|
||||
- Added module info page to web UI
|
||||
- Added realtime override functionality to web UI
|
||||
- Added individial segment power and brightness to web UI
|
||||
- Added feature to one-click select single segment only by tapping segment name
|
||||
- Removed palette jumping to default if color is changed
|
||||
|
||||
#### Build 2004300
|
||||
|
||||
- Added realtime override option and `lor` JSON property
|
||||
- Added `lm` (live mode) and `lip` (live IP) properties to info in JSON API
|
||||
- Added reset commands to APIs
|
||||
- Added `json/si`, returning state and info, but no FX or Palette lists
|
||||
- Added rollover detection to millis(). Can track uptimes longer than 49 days
|
||||
- Attempted to fix Wifi issues with Unifi brand APs
|
||||
|
||||
#### Build 2004230
|
||||
|
||||
- Added brightness and power for individual segments
|
||||
- Added `on` and `bri` properties to Segment object in JSON API
|
||||
- Added `C3` an `SB` commands to HTTP get API
|
||||
- Merged pull request #865 for 5CH_Shojo_PCB environment
|
||||
|
||||
#### Build 2004220
|
||||
|
||||
- Added Candle Multi effect
|
||||
- Added Palette capability to Pacifica effect
|
||||
|
||||
#### Build 2004190
|
||||
|
||||
- Added TM1814 type LED defines
|
||||
|
||||
#### Build 2004120
|
||||
|
||||
- Added Art-Net support
|
||||
- Added OTA platform to platformio.ini
|
||||
|
||||
#### Build 2004100
|
||||
|
||||
- Fixed DMX output compilation
|
||||
- Added DMX start LED setting
|
||||
|
||||
#### Build 2004061
|
||||
|
||||
- Fixed RBG and BGR getPixelColor (#825)
|
||||
- Improved formatting
|
||||
|
||||
#### Build 2004060
|
||||
|
||||
- Consolidated global variables in wled.h
|
||||
|
||||
#### Build 2003300
|
||||
|
||||
- Major change of project structure from .ino to .cpp and func_declare.h
|
||||
|
||||
#### Build 2003262
|
||||
|
||||
- Fixed compilation for Analog LEDs
|
||||
- Fixed sync settings network port fields too small
|
||||
|
||||
#### Build 2003261
|
||||
|
||||
- Fixed live preview not displaying whole light if over 255 LEDs
|
||||
|
||||
#### Build 2003251
|
||||
|
||||
- Added Pacifica effect (tentative, doesn't yet support other colors)
|
||||
- Added Atlantica palette
|
||||
- Fixed ESP32 build of Espalexa
|
||||
|
||||
#### Build 2003222
|
||||
|
||||
- Fixed Alexa Whites on non-RGBW lights (bump Espalexa to 2.4.5)
|
||||
|
||||
#### Build 2003221
|
||||
|
||||
- Moved Cronixie driver from FX library to drawOverlay handler
|
||||
|
||||
#### Build 2003211
|
||||
|
||||
- Added custom mapping compile define to FX_fcn.h
|
||||
- Merged pull request #784 by @TravisDean: Fixed initialization bug when toggling skip first
|
||||
- Added link to youtube videos by Room31 to readme
|
||||
|
||||
#### Build 2003141
|
||||
|
||||
- Fixed color of main segment returned in JSON API during transition not being target color (closes #765)
|
||||
- Fixed arlsLock() being called after pixels set in E1.31 (closes #772)
|
||||
- Fixed HTTP API calls not having an effect if no segment selected (now applies to main segment)
|
||||
|
||||
#### Build 2003121
|
||||
|
||||
- Created changelog.md - make tracking changes to code easier
|
||||
- Merged pull request #766 by @pille: Fix E1.31 out-of sequence detection
|
||||
|
76
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at dev.aircoookie@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
@@ -1,7 +0,0 @@
|
||||
## Where are the new binaries?
|
||||
|
||||
From v0.5.0 on forward, the GitHub [releases](https://github.com/Aircoookie/WLED/releases) system will be used for binaries.
|
||||
|
||||
### What binary should I choose?
|
||||
|
||||
You should always try to use the binaries from the release page. This directory is for legacy purposes only!
|
BIN
images/macbook-pro-space-gray-on-the-wooden-table.jpg
Normal file
After Width: | Height: | Size: 490 KiB |
BIN
images/walking-with-iphone-x.jpg
Normal file
After Width: | Height: | Size: 500 KiB |
BIN
images/wled_logo.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
images/wled_logo_akemi.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
images/wled_logo_clean.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
39
include/README
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
lib/README
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
2233
package-lock.json
generated
Normal file
31
package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.10.2",
|
||||
"description": "Tools for WLED project",
|
||||
"main": "tools/cdata.js",
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node tools/cdata.js",
|
||||
"dev": "nodemon -e js,html,htm,css,png,jpg,gif,ico,js -w tools/ -w wled00/data/ -x node tools/cdata.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Aircoookie/WLED.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Aircoookie/WLED/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Aircoookie/WLED#readme",
|
||||
"dependencies": {
|
||||
"clean-css": "^4.2.3",
|
||||
"html-minifier": "^4.0.0",
|
||||
"inliner": "^1.13.1",
|
||||
"nodemon": "^2.0.4",
|
||||
"zlib": "^1.0.5"
|
||||
}
|
||||
}
|
368
platformio.ini
Normal file
@@ -0,0 +1,368 @@
|
||||
; PlatformIO Project Configuration File
|
||||
; Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
src_dir = ./wled00
|
||||
data_dir = ./wled00/data
|
||||
lib_dir = ./wled00/src
|
||||
build_cache_dir = ~/.buildcache
|
||||
extra_configs =
|
||||
platformio_override.ini
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ENVIRONMENTS
|
||||
#
|
||||
# Please uncomment one of the lines below to select your board(s)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Travis CI binaries
|
||||
default_envs = travis_esp8266, travis_esp32
|
||||
|
||||
# Release binaries
|
||||
; default_envs = nodemcuv2, esp01_1m_full, esp32dev, custom_WS2801, custom_APA102, custom_LEDPIN_16, custom_LEDPIN_4, custom_LEDPIN_3, custom32_LEDPIN_16
|
||||
|
||||
# Single binaries (uncomment your board)
|
||||
; default_envs = nodemcuv2
|
||||
; default_envs = esp01
|
||||
; default_envs = esp01_1m_ota
|
||||
; default_envs = esp01_1m_full
|
||||
; default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
; default_envs = heltec_wifi_kit_8
|
||||
; default_envs = h803wf
|
||||
; default_envs = d1_mini_debug
|
||||
; default_envs = d1_mini_ota
|
||||
; default_envs = esp32dev
|
||||
; default_envs = esp8285_4CH_MagicHome
|
||||
; default_envs = esp8285_4CH_H801
|
||||
; default_envs = esp8285_5CH_H801
|
||||
; default_envs = d1_mini_5CH_Shojo_PCB
|
||||
; default_envs = wemos_shield_esp32
|
||||
; default_envs = m5atom
|
||||
|
||||
[common]
|
||||
# ------------------------------------------------------------------------------
|
||||
# PLATFORM:
|
||||
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
|
||||
#
|
||||
# arduino core 2.3.0 = platformIO 1.5.0
|
||||
# arduino core 2.4.0 = platformIO 1.6.0
|
||||
# arduino core 2.4.1 = platformIO 1.7.3
|
||||
# arduino core 2.4.2 = platformIO 1.8.0
|
||||
# arduino core 2.5.0 = platformIO 2.0.4
|
||||
# arduino core 2.5.1 = platformIO 2.1.1
|
||||
# arduino core 2.5.2 = platformIO 2.2.3
|
||||
# arduino core 2.6.1 = platformIO 2.3.0
|
||||
# arduino core 2.6.2 = platformIO 2.3.1
|
||||
# arduino core 2.6.3 = platformIO 2.3.2
|
||||
# arduino core 2.7.0 = platformIO 2.5.0
|
||||
# ------------------------------------------------------------------------------
|
||||
arduino_core_2_3_0 = espressif8266@1.5.0
|
||||
arduino_core_2_4_0 = espressif8266@1.6.0
|
||||
arduino_core_2_4_1 = espressif8266@1.7.3
|
||||
arduino_core_2_4_2 = espressif8266@1.8.0
|
||||
arduino_core_2_5_0 = espressif8266@2.0.4
|
||||
arduino_core_2_5_1 = espressif8266@2.1.1
|
||||
arduino_core_2_5_2 = espressif8266@2.2.3
|
||||
arduino_core_2_6_1 = espressif8266@2.3.0
|
||||
arduino_core_2_6_2 = espressif8266@2.3.1
|
||||
arduino_core_2_6_3 = espressif8266@2.3.3
|
||||
arduino_core_2_7_1 = espressif8266@2.5.1
|
||||
arduino_core_2_7_2 = espressif8266@2.6.0
|
||||
arduino_core_2_7_3 = espressif8266@2.6.1
|
||||
arduino_core_2_7_4 = espressif8266@2.6.2
|
||||
|
||||
# Development platforms
|
||||
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
||||
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
|
||||
|
||||
# Platform to use for ESP8266
|
||||
platform_wled_default = ${common.arduino_core_2_7_4}
|
||||
# We use 2.7.0+ on analog boards because of PWM flicker fix
|
||||
platform_latest = ${common.arduino_core_2_7_4}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# FLAGS: DEBUG
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
debug_flags = -D DEBUG=1 -D WLED_DEBUG -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM
|
||||
#if needed (for memleaks etc) also add; -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h"
|
||||
#-DDEBUG_ESP_CORE is not working right now
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# FLAGS: ldscript
|
||||
# ldscript_512k ( 512 KB) = 487 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
|
||||
# ldscript_1m0m (1024 KB) = 999 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
|
||||
# ldscript_2m1m (2048 KB) = 1019 KB sketch, 4 KB eeprom, 1004 KB spiffs, 16 KB reserved
|
||||
# ldscript_4m1m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 1002 KB spiffs, 16 KB reserved, 2048 KB empty/ota?
|
||||
# ldscript_4m3m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 3040 KB spiffs, 16 KB reserved
|
||||
#
|
||||
# Available lwIP variants (macros):
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH = v1.4 Higher Bandwidth (default)
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY = v2 Lower Memory
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH = v2 Higher Bandwidth
|
||||
#
|
||||
# BearSSL performance:
|
||||
# When building with -DSECURE_CLIENT=SECURE_CLIENT_BEARSSL, please add `board_build.f_cpu = 160000000` to the environment configuration
|
||||
#
|
||||
# BearSSL ciphers:
|
||||
# When building on core >= 2.5, you can add the build flag -DBEARSSL_SSL_BASIC in order to build BearSSL with a limited set of ciphers:
|
||||
# TLS_RSA_WITH_AES_128_CBC_SHA256 / AES128-SHA256
|
||||
# TLS_RSA_WITH_AES_256_CBC_SHA256 / AES256-SHA256
|
||||
# TLS_RSA_WITH_AES_128_CBC_SHA / AES128-SHA
|
||||
# TLS_RSA_WITH_AES_256_CBC_SHA / AES256-SHA
|
||||
# This reduces the OTA size with ~45KB, so it's especially useful on low memory boards (512k/1m).
|
||||
# ------------------------------------------------------------------------------
|
||||
build_flags = -g -w -DMQTT_MAX_PACKET_SIZE=1024 -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
-DSECURE_CLIENT=SECURE_CLIENT_BEARSSL -DBEARSSL_SSL_BASIC
|
||||
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
|
||||
-D _IR_ENABLE_DEFAULT_=false
|
||||
-D DECODE_HASH=true
|
||||
-D DECODE_NEC=true
|
||||
-D DECODE_SONY=true
|
||||
-D DECODE_SAMSUNG=true
|
||||
-D DECODE_LG=true
|
||||
|
||||
build_flags_esp8266 = ${common.build_flags} -DESP8266
|
||||
build_flags_esp32 = ${common.build_flags} -DARDUINO_ARCH_ESP32
|
||||
|
||||
# enables all features for travis CI
|
||||
build_flags_all_features =
|
||||
-D WLED_USE_ANALOG_LED
|
||||
-D WLED_USE_H801
|
||||
-D WLED_ENABLE_5CH_LEDS
|
||||
-D WLED_ENABLE_ADALIGHT
|
||||
-D WLED_ENABLE_DMX
|
||||
-D WLED_ENABLE_MQTT
|
||||
-D WLED_ENABLE_WEBSOCKETS
|
||||
|
||||
ldscript_512k = eagle.flash.512k.ld ;for older versions change this to eagle.flash.512k0.ld
|
||||
ldscript_1m0m = eagle.flash.1m.ld ;for older versions change this to eagle.flash.1m0.ld
|
||||
ldscript_2m1m = eagle.flash.2m1m.ld
|
||||
ldscript_4m1m = eagle.flash.4m1m.ld
|
||||
ldscript_4m3m = eagle.flash.4m3m.ld
|
||||
|
||||
shared_libdeps_dir = ./wled00/src
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# COMMON SETTINGS:
|
||||
# ------------------------------------------------------------------------------
|
||||
[env]
|
||||
framework = arduino
|
||||
board_build.flash_mode = dout
|
||||
monitor_speed = 115200
|
||||
upload_speed = 115200
|
||||
lib_extra_dirs =
|
||||
${common.shared_libdeps_dir}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# LIBRARIES: required dependencies
|
||||
# Please note that we don't always use the latest version of a library.
|
||||
#
|
||||
# The following libraries have been included (and some of them changd) in the source:
|
||||
# ArduinoJson@5.13.5, Blynk@0.5.4(changed), E131@1.0.0(changed), Time@1.5, Timezone@1.2.1
|
||||
# ------------------------------------------------------------------------------
|
||||
lib_compat_mode = strict
|
||||
lib_deps =
|
||||
FastLED@3.3.2
|
||||
NeoPixelBus@2.5.7
|
||||
ESPAsyncTCP@1.2.0
|
||||
ESPAsyncUDP
|
||||
AsyncTCP@1.0.3
|
||||
https://github.com/Aircoookie/ESPAsyncWebServer
|
||||
IRremoteESP8266@2.7.3
|
||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||
#TFT_eSPI
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
#U8g2@~2.27.2
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
#OneWire@~2.3.5
|
||||
#For BME280 sensor uncomment following
|
||||
#BME280@~3.0.0
|
||||
lib_ignore =
|
||||
AsyncTCP
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# WLED BUILDS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[env:nodemcuv2]
|
||||
board = nodemcuv2
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
# Unsupported environment due to insufficient flash
|
||||
[env:esp01]
|
||||
board = esp01
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_512k}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED -D WLED_DISABLE_MQTT -D WLED_DISABLE_WEBSOCKETS
|
||||
|
||||
# Unsupported environment due to insufficient flash
|
||||
[env:esp01_1m_ota]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE
|
||||
-D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED -D WLED_DISABLE_MQTT -D WLED_DISABLE_WEBSOCKETS
|
||||
|
||||
[env:esp01_1m_full]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||
|
||||
[env:esp07]
|
||||
board = esp07
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:d1_mini]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_wled_default}
|
||||
upload_speed = 921600
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:heltec_wifi_kit_8]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:h803wf]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||
|
||||
[env:esp32dev]
|
||||
board = esp32dev
|
||||
platform = espressif32@1.12.4
|
||||
build_flags = ${common.build_flags_esp32}
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
||||
[env:esp8285_4CH_MagicHome]
|
||||
board = esp8285
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS
|
||||
|
||||
[env:esp8285_4CH_H801]
|
||||
board = esp8285
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801
|
||||
|
||||
[env:esp8285_5CH_H801]
|
||||
board = esp8285
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801 -D WLED_ENABLE_5CH_LEDS
|
||||
|
||||
[env:d1_mini_5CH_Shojo_PCB]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_USE_ANALOG_LEDS -D WLED_USE_SHOJO_PCB -D WLED_ENABLE_5CH_LEDS
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# DEVELOPMENT BOARDS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[env:d1_mini_debug]
|
||||
board = d1_mini
|
||||
build_type = debug
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} ${common.debug_flags}
|
||||
|
||||
[env:d1_mini_ota]
|
||||
board = d1_mini
|
||||
upload_protocol = espota
|
||||
# exchange for your WLED IP
|
||||
upload_port = "10.10.1.27"
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# custom board configurations
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[env:custom_LEDPIN_4]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=4 -D IRPIN=5
|
||||
|
||||
[env:custom_LEDPIN_16]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=16
|
||||
|
||||
|
||||
[env:custom_LEDPIN_3]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3
|
||||
|
||||
[env:custom_APA102]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D USE_APA102
|
||||
|
||||
[env:custom_WS2801]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D USE_WS2801
|
||||
|
||||
[env:custom32_LEDPIN_16]
|
||||
board = esp32dev
|
||||
platform = espressif32@1.12.4
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=16
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
||||
[env:wemos_shield_esp32]
|
||||
board = esp32dev
|
||||
platform = espressif32@1.12.4
|
||||
upload_port = /dev/cu.SLAB_USBtoUART
|
||||
monitor_port = /dev/cu.SLAB_USBtoUART
|
||||
upload_speed = 460800
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=16 -D RLYPIN=19 -D BTNPIN=17
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
||||
[env:m5atom]
|
||||
board = esp32dev
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=27 -D BTNPIN=39
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
platform = espressif32@1.12.4
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# travis test board configurations
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[env:travis_esp8266]
|
||||
extends = env:d1_mini
|
||||
build_type = debug
|
||||
build_flags = ${common.build_flags_esp8266} ${common.debug_flags} ${common.build_flags_all_features}
|
||||
|
||||
[env:travis_esp32]
|
||||
extends = env:esp32dev
|
||||
build_type = debug
|
||||
build_flags = ${common.build_flags_esp32} ${common.debug_flags} ${common.build_flags_all_features}
|
42
platformio_override.ini.example
Normal file
@@ -0,0 +1,42 @@
|
||||
# Example PlatformIO Project Configuration Override
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copy to platformio_override.ini to activate overrides
|
||||
# ------------------------------------------------------------------------------
|
||||
# Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
default_envs = esp8266_1m_custom
|
||||
|
||||
[env:esp8266_1m_custom]
|
||||
board = esp01_1m
|
||||
platform = ${common.arduino_core_2_4_2}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
-D WLED_DISABLE_OTA
|
||||
-D WLED_DISABLE_ALEXA
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
-D WLED_DISABLE_INFRARED
|
||||
; PIN defines - uncomment and change, if needed:
|
||||
; -D LEDPIN=2
|
||||
; -D BTNPIN=0
|
||||
; -D IR_PIN=4
|
||||
; -D RLYPIN=12
|
||||
; -D RLYMDE=1
|
||||
; digital LED strip types - uncomment only one ! - this will disable WS281x / SK681x support
|
||||
; -D USE_APA102
|
||||
; -D USE_WS2801
|
||||
; -D USE_LPD8806
|
||||
; PIN defines for 2 wire LEDs
|
||||
; -D CLKPIN=0
|
||||
; -D DATAPIN=2
|
||||
; to drive analog LED strips (aka 5050), uncomment the following
|
||||
; PWM pins 5,12,13,15 are used with Magic Home LED Controller (default)
|
||||
; -D WLED_USE_ANALOG_LEDS
|
||||
; for the H801 controller (PINs 15,13,12,14 (W2 = 04)) uncomment this
|
||||
; -D WLED_USE_H801
|
||||
; for the BW-LT11 controller (PINs 12,4,14,5 ) uncomment this
|
||||
; -D WLED_USE_BWLT11
|
||||
; and to enable channel 5 for RGBW-CT led strips this
|
||||
; -D WLED_USE_5CH_LEDS
|
127
readme.md
@@ -1,50 +1,103 @@
|
||||
## Welcome to my project WLED!
|
||||
<p align="center">
|
||||
<img src="/images/wled_logo_akemi.png">
|
||||
<a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a>
|
||||
<a href="https://wled.discourse.group"><img src="https://img.shields.io/discourse/topics?colorB=blue&label=forum&server=https%3A%2F%2Fwled.discourse.group%2F&style=flat-square"></a>
|
||||
<a href="https://discord.gg/KuqP7NE"><img src="https://img.shields.io/discord/473448917040758787.svg?colorB=blue&label=discord&style=flat-square"></a>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki"><img src="https://img.shields.io/badge/quick_start-wiki-blue.svg?style=flat-square"></a>
|
||||
<a href="https://github.com/Aircoookie/WLED-App"><img src="https://img.shields.io/badge/app-wled-blue.svg?style=flat-square"></a>
|
||||
</p>
|
||||
|
||||
# Welcome to my project WLED! ✨
|
||||
|
||||
WLED is a fast and (relatively) secure implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B) LEDs!
|
||||
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs or also SPI based chipsets like the WS2801!
|
||||
|
||||
### Features: (V0.6.3)
|
||||
- RGB, HSB, and brightness sliders
|
||||
- Settings page - configuration over network
|
||||
- Access Point and station mode - automatic failsafe AP
|
||||
- WS2812FX library integrated for over 50 special effects!
|
||||
- Secondary color support lets you use even more effect combinations
|
||||
- Alexa smart home device server (including dimming)
|
||||
- Beta syncronization to Philips hue lights
|
||||
- Support for RGBW strips
|
||||
- 25 user presets! Save your favorite colors and effects and apply them easily! Now supports cycling through them.
|
||||
- HTTP request API for simple integration
|
||||
- Macro functions to automatically execute API calls
|
||||
- Nightlight function (gradually dims down)
|
||||
- Notifier function (multiple ESPs sync color via UDP broadcast)
|
||||
- Support for power pushbutton
|
||||
- Custom Theater Chase
|
||||
- Support for the Adalight serial ambilight protocol!
|
||||
- Full OTA software update capability (HTTP and ArduinoOTA)
|
||||
- Password protected OTA page for added security (OTA lock)
|
||||
- NTP and configurable analog clock function
|
||||
- Support for the Cronixie Clock kit by Diamex
|
||||
- Realtime UDP Packet Control (WARLS, DRGB, DRGBW) possible
|
||||
- Client HTML UI controlled, customizable themes
|
||||
## ⚙️ Features
|
||||
- WS2812FX library integrated for over 100 special effects
|
||||
- FastLED noise effects and 50 palettes
|
||||
- Modern UI with color, effect and segment controls
|
||||
- Segments to set different effects and colors to parts of the LEDs
|
||||
- Settings page - configuration over network
|
||||
- Access Point and station mode - automatic failsafe AP
|
||||
- Support for RGBW strips
|
||||
- 16 user presets to save and load colors/effects easily, supports cycling through them.
|
||||
- Macro functions to automatically execute API calls
|
||||
- Nightlight function (gradually dims down)
|
||||
- Full OTA software updatability (HTTP + ArduinoOTA), password protectable
|
||||
- Configurable analog clock + support for the Cronixie kit by Diamex
|
||||
- Configurable Auto Brightness limit for safer operation
|
||||
|
||||
### Quick start guide and documentation:
|
||||
## 💡 Supported light control interfaces
|
||||
- WLED app for [Android](https://play.google.com/store/apps/details?id=com.aircoookie.WLED) and [iOS](https://apps.apple.com/us/app/wled/id1475695033)
|
||||
- JSON and HTTP request APIs
|
||||
- MQTT
|
||||
- Blynk IoT
|
||||
- E1.31, Art-Net and TPM2.net
|
||||
- [Hyperion](https://github.com/hyperion-project/hyperion.ng)
|
||||
- UDP realtime
|
||||
- Alexa voice control (including dimming and color)
|
||||
- Sync to Philips hue lights
|
||||
- Adalight (PC ambilight via serial) and TPM2
|
||||
- Sync color of multiple WLED devices (UDP notifier)
|
||||
- Infrared remotes (24-key RGB, receiver required)
|
||||
- Simple timers/schedules (time from NTP, timezones/DST supported)
|
||||
|
||||
## 📲 Quick start guide and documentation
|
||||
|
||||
See the [wiki](https://github.com/Aircoookie/WLED/wiki)!
|
||||
|
||||
### Other
|
||||
DrZzs has made some excellent video guides:
|
||||
[Introduction, hardware and installation](https://www.youtube.com/watch?v=tXvtxwK3jRk)
|
||||
[Settings, tips and tricks](https://www.youtube.com/watch?v=6eCE2BpLaUQ)
|
||||
|
||||
Licensed under the MIT license
|
||||
Uses libraries:
|
||||
ESP8266/ESP32 Arduino Core
|
||||
NeoPixelBus by Makuna
|
||||
[WS2812FX](https://github.com/kitesurfer1404/WS2812FX) by kitesurfer1404 (Aircoookie fork)
|
||||
Time library
|
||||
Timezone library by JChristensen
|
||||
Alexa code based on arduino-esp8266-alexa-multiple-wemo-switch by kakopappa
|
||||
|
||||
Uses Linearicons by Perxis! (link in settings page)
|
||||
If you'd rather read, here is a very [detailed step-by-step beginner tutorial](https://tynick.com/blog/11-03-2019/getting-started-with-wled-on-esp8266/) by tynick!
|
||||
|
||||
Russian speakers, check out the videos by Room31:
|
||||
[WLED Firmware Overview: Interface and Settings](https://youtu.be/h7lKsczEI7E)
|
||||
[ESP8266 based LED controller for WS2812b strip. WLED Firmware + OpenHAB](https://youtu.be/K4ioTt3XvGc)
|
||||
|
||||
## 🖼️ Images
|
||||
<img src="/images/macbook-pro-space-gray-on-the-wooden-table.jpg" width="50%"><img src="/images/walking-with-iphone-x.jpg" width="50%">
|
||||
|
||||
## 💾 Compatible LED Strips
|
||||
Type | Voltage | Comments
|
||||
|---|---|---|
|
||||
WS2812B | 5v |
|
||||
WS2813 | 5v |
|
||||
SK6812 | 5v | RGBW
|
||||
APA102 | 5v | C/D
|
||||
WS2801 | 5v | C/D
|
||||
LPD8806 | 5v | C/D
|
||||
TM1814 | 12v | RGBW
|
||||
WS2811 | 12v | 3-LED segments
|
||||
WS2815 | 12v |
|
||||
GS8208 | 12v |
|
||||
|
||||
## 🧊 Compatibe PC RGB Fans and ARGB accessories
|
||||
Brand | Model | Comments
|
||||
|---|---|---|
|
||||
Corsair | HD120 Fan | Uses WS2812B, data-in only
|
||||
PCCOOLER | Moonlight 5-pack Fans | Uses WS2812B, includes Data-out connector to keep each fan uniquely addressable if wired in series like traditional LED strips
|
||||
Any | 5v 3-pin ARGB for PC | Any PC RGB device that supports the 5v 3-pin ARGB motherboard header should work fine with WLED. All the major motherboard vendors support the Corsair HD120 and PCCOOLER fans listed, so we can safely assume any device that supports motherboard ARGB 5V 3-Pin standard will work with WLED.
|
||||
|
||||
|
||||
## ✌️ Other
|
||||
|
||||
Licensed under the MIT license
|
||||
Credits [here](https://github.com/Aircoookie/WLED/wiki/Contributors-&-About)!
|
||||
|
||||
Uses Linearicons by Perxis!
|
||||
|
||||
Join the Discord server to discuss everything about WLED!
|
||||
|
||||
<a href="https://discord.gg/KuqP7NE"><img src="https://discordapp.com/api/guilds/473448917040758787/widget.png?style=banner2" width="25%"></a>
|
||||
|
||||
Check out the WLED [Discourse forum](https://wled.discourse.group)!
|
||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com), but please only do so if you want to talk to me privately.
|
||||
If WLED really brightens up your every day, you can [](https://paypal.me/aircoookie)
|
||||
|
||||
|
||||
*Disclaimer:*
|
||||
If you are sensitive to photoeleptic seizures it is not recommended that you use this software.
|
||||
In case you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
|
||||
As per the MIT license, i assume no liability for any damage to you or any other person or equipment.
|
||||
|
||||
|
11
test/README
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
396
tools/cdata.js
Normal file
@@ -0,0 +1,396 @@
|
||||
/**
|
||||
* Writes compressed C arrays of data files (web interface)
|
||||
* How to use it?
|
||||
*
|
||||
* 1) Install Node 11+ and npm
|
||||
* 2) npm install
|
||||
* 3) npm run build
|
||||
*
|
||||
* If you change data folder often, you can run it in monitoring mode (it will recompile and update *.h on every file change)
|
||||
*
|
||||
* > npm run dev
|
||||
*
|
||||
* How it works?
|
||||
*
|
||||
* It uses NodeJS packages to inline, minify and GZIP files. See writeHtmlGzipped and writeChunks invocations at the bottom of the page.
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const packageJson = require("../package.json");
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function hexdump(buffer) {
|
||||
let lines = [];
|
||||
|
||||
for (let i = 0; i < buffer.length; i += 16) {
|
||||
let block = buffer.slice(i, i + 16); // cut buffer into blocks of 16
|
||||
let hexArray = [];
|
||||
|
||||
for (let value of block) {
|
||||
hexArray.push("0x" + value.toString(16).padStart(2, "0"));
|
||||
}
|
||||
|
||||
let hexString = hexArray.join(", ");
|
||||
let line = ` ${hexString}`;
|
||||
lines.push(line);
|
||||
}
|
||||
|
||||
return lines.join(",\n");
|
||||
}
|
||||
|
||||
const inliner = require("inliner");
|
||||
const zlib = require("zlib");
|
||||
|
||||
function strReplace(str, search, replacement) {
|
||||
return str.split(search).join(replacement);
|
||||
}
|
||||
|
||||
function adoptVersionAndRepo(html) {
|
||||
let repoUrl = packageJson.repository ? packageJson.repository.url : undefined;
|
||||
if (repoUrl) {
|
||||
repoUrl = repoUrl.replace(/^git\+/, "");
|
||||
repoUrl = repoUrl.replace(/\.git$/, "");
|
||||
// Replace we
|
||||
html = strReplace(html, "https://github.com/atuline/WLED", repoUrl);
|
||||
html = strReplace(html, "https://github.com/Aircoookie/WLED", repoUrl);
|
||||
}
|
||||
|
||||
let version = packageJson.version;
|
||||
if (version) {
|
||||
html = strReplace(html, "##VERSION##", version);
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function writeHtmlGzipped(sourceFile, resultFile) {
|
||||
console.info("Reading " + sourceFile);
|
||||
new inliner(sourceFile, function (error, html) {
|
||||
console.info("Inlined " + html.length + " characters");
|
||||
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
html = adoptVersionAndRepo(html);
|
||||
zlib.gzip(html, { level: zlib.constants.Z_BEST_COMPRESSION }, function (error, result) {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.info("Compressed " + result.length + " bytes");
|
||||
const array = hexdump(result);
|
||||
const src = `/*
|
||||
* Binary array for the Web UI.
|
||||
* gzip is used for smaller size and improved speeds.
|
||||
*
|
||||
* Please see https://github.com/Aircoookie/WLED/wiki/Add-own-functionality#web-ui
|
||||
* to find out how to easily modify the web UI source!
|
||||
*/
|
||||
|
||||
// Autogenerated from ${sourceFile}, do not edit!!
|
||||
const uint16_t PAGE_index_L = ${result.length};
|
||||
const uint8_t PAGE_index[] PROGMEM = {
|
||||
${array}
|
||||
};
|
||||
`;
|
||||
console.info("Writing " + resultFile);
|
||||
fs.writeFileSync(resultFile, src);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const CleanCSS = require("clean-css");
|
||||
const MinifyHTML = require("html-minifier").minify;
|
||||
|
||||
function filter(str, type) {
|
||||
str = adoptVersionAndRepo(str);
|
||||
|
||||
if (type === undefined) {
|
||||
return str;
|
||||
} else if (type == "css-minify") {
|
||||
return new CleanCSS({}).minify(str).styles;
|
||||
} else if (type == "html-minify") {
|
||||
return MinifyHTML(str, {
|
||||
collapseWhitespace: true,
|
||||
maxLineLength: 80,
|
||||
minifyCSS: true,
|
||||
minifyJS: true,
|
||||
continueOnParseError: false,
|
||||
removeComments: true,
|
||||
});
|
||||
} else {
|
||||
console.warn("Unknown filter: " + type);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
function specToChunk(srcDir, s) {
|
||||
if (s.method == "plaintext") {
|
||||
const buf = fs.readFileSync(srcDir + "/" + s.file);
|
||||
const str = buf.toString("ascii");
|
||||
const chunk = `
|
||||
// Autogenerated from ${srcDir}/${s.file}, do not edit!!
|
||||
const char ${s.name}[] PROGMEM = R"${s.prepend || ""}${filter(str, s.filter)}${
|
||||
s.append || ""
|
||||
}";
|
||||
|
||||
`;
|
||||
return s.mangle ? s.mangle(chunk) : chunk;
|
||||
} else if (s.method == "binary") {
|
||||
const buf = fs.readFileSync(srcDir + "/" + s.file);
|
||||
const result = hexdump(buf);
|
||||
const chunk = `
|
||||
// Autogenerated from ${srcDir}/${s.file}, do not edit!!
|
||||
const uint16_t ${s.name}_length = ${result.length};
|
||||
const uint8_t ${s.name}[] PROGMEM = {
|
||||
${result}
|
||||
};
|
||||
|
||||
`;
|
||||
return s.mangle ? s.mangle(chunk) : chunk;
|
||||
} else {
|
||||
console.warn("Unknown method: " + s.method);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function writeChunks(srcDir, specs, resultFile) {
|
||||
let src = `/*
|
||||
* More web UI HTML source arrays.
|
||||
* This file is auto generated, please don't make any changes manually.
|
||||
* Instead, see https://github.com/Aircoookie/WLED/wiki/Add-own-functionality#web-ui
|
||||
* to find out how to easily modify the web UI source!
|
||||
*/
|
||||
`;
|
||||
specs.forEach((s) => {
|
||||
try {
|
||||
console.info("Reading " + srcDir + "/" + s.file + " as " + s.name);
|
||||
src += specToChunk(srcDir, s);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
"Failed " + s.name + " from " + srcDir + "/" + s.file,
|
||||
e.message.length > 60 ? e.message.substring(0, 60) : e.message
|
||||
);
|
||||
}
|
||||
});
|
||||
console.info("Writing " + src.length + " characters into " + resultFile);
|
||||
fs.writeFileSync(resultFile, src);
|
||||
}
|
||||
|
||||
writeHtmlGzipped("wled00/data/index.htm", "wled00/html_ui.h");
|
||||
|
||||
writeChunks(
|
||||
"wled00/data",
|
||||
[
|
||||
{
|
||||
file: "style.css",
|
||||
name: "PAGE_settingsCss",
|
||||
prepend: "=====(<style>",
|
||||
append: "</style>)=====",
|
||||
method: "plaintext",
|
||||
filter: "css-minify",
|
||||
},
|
||||
{
|
||||
file: "settings.htm",
|
||||
name: "PAGE_settings",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace("%", "%%")
|
||||
.replace(/User Interface\<\/button\>\<\/form\>/gms, "User Interface\<\/button\>\<\/form\>%DMXMENU%"),
|
||||
},
|
||||
{
|
||||
file: "settings_wifi.htm",
|
||||
name: "PAGE_settings_wifi",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"function GetV() {var d=document;\n"
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "settings_leds.htm",
|
||||
name: "PAGE_settings_leds",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"function GetV() {var d=document;\n"
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "settings_dmx.htm",
|
||||
name: "PAGE_settings_dmx",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) => {
|
||||
const nocss = str
|
||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"function GetV() {var d=document;\n"
|
||||
);
|
||||
return `
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
${nocss}
|
||||
#else
|
||||
const char PAGE_settings_dmx[] PROGMEM = R"=====()=====";
|
||||
#endif
|
||||
`;
|
||||
},
|
||||
},
|
||||
{
|
||||
file: "settings_ui.htm",
|
||||
name: "PAGE_settings_ui",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"function GetV() {var d=document;\n"
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "settings_sync.htm",
|
||||
name: "PAGE_settings_sync",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||
.replace(/function GetV().*\<\/script\>/gms, "function GetV() {\n"),
|
||||
},
|
||||
{
|
||||
file: "settings_time.htm",
|
||||
name: "PAGE_settings_time",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||
.replace(/function GetV().*\<\/script\>/gms, "function GetV() {\n"),
|
||||
},
|
||||
{
|
||||
file: "settings_sec.htm",
|
||||
name: "PAGE_settings_sec",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"function GetV() {var d=document;\n"
|
||||
),
|
||||
},
|
||||
],
|
||||
"wled00/html_settings.h"
|
||||
);
|
||||
|
||||
writeChunks(
|
||||
"wled00/data",
|
||||
[
|
||||
{
|
||||
file: "usermod.htm",
|
||||
name: "PAGE_usermod",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str.replace(/fetch\("http\:\/\/.*\/win/gms, 'fetch("/win'),
|
||||
},
|
||||
{
|
||||
file: "msg.htm",
|
||||
name: "PAGE_msg",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) => str.replace(/\<h2\>.*\<\/body\>/gms, "<h2>%MSG%</body>"),
|
||||
},
|
||||
{
|
||||
file: "dmxmap.htm",
|
||||
name: "PAGE_dmxmap",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
mangle: (str) => `
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
${str.replace(/function FM\(\)[ ]?\{/gms, "function FM() {%DMXVARS%\n")}
|
||||
#else
|
||||
const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
|
||||
#endif
|
||||
`,
|
||||
},
|
||||
{
|
||||
file: "update.htm",
|
||||
name: "PAGE_update",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
},
|
||||
{
|
||||
file: "welcome.htm",
|
||||
name: "PAGE_welcome",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
},
|
||||
{
|
||||
file: "liveview.htm",
|
||||
name: "PAGE_liveview",
|
||||
prepend: "=====(",
|
||||
append: ")=====",
|
||||
method: "plaintext",
|
||||
filter: "html-minify",
|
||||
},
|
||||
{
|
||||
file: "favicon.ico",
|
||||
name: "favicon",
|
||||
method: "binary",
|
||||
},
|
||||
],
|
||||
"wled00/html_other.h"
|
||||
);
|
10
usermods/EXAMPLE_v2/readme.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Usermods API v2 example usermod
|
||||
|
||||
In this usermod file you can find the documentation on how to take advantage of the new version 2 usermods!
|
||||
|
||||
## Installation
|
||||
|
||||
Copy `usermod_v2_example.h` to the wled00 directory.
|
||||
Uncomment the corresponding lines in `usermods_list.cpp` and compile!
|
||||
_(You shouldn't need to actually install this, it does nothing useful)_
|
||||
|
119
usermods/EXAMPLE_v2/usermod_v2_example.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Usermods allow you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
*
|
||||
* This is an example for a v2 usermod.
|
||||
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
|
||||
* Multiple v2 usermods can be added to one compilation easily.
|
||||
*
|
||||
* Creating a usermod:
|
||||
* This file serves as an example. If you want to create a usermod, it is recommended to use usermod_v2_empty.h from the usermods folder as a template.
|
||||
* Please remember to rename the class and file to a descriptive name.
|
||||
* You may also use multiple .h and .cpp files.
|
||||
*
|
||||
* Using a usermod:
|
||||
* 1. Copy the usermod into the sketch folder (same folder as wled00.ino)
|
||||
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||
*/
|
||||
|
||||
//class name. Use something descriptive and leave the ": public Usermod" part :)
|
||||
class MyExampleUsermod : public Usermod {
|
||||
private:
|
||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
unsigned long lastTime = 0;
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup() {
|
||||
//Serial.println("Hello from my usermod!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected() {
|
||||
//Serial.println("Connected to WiFi!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop() {
|
||||
if (millis() - lastTime > 1000) {
|
||||
//Serial.println("I'm alive!");
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
/*
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
*/
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_EXAMPLE;
|
||||
}
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png
Normal file
After Width: | Height: | Size: 235 KiB |
7
usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Enclosure and PCB
|
||||
|
||||
## IP67 rated enclosure
|
||||

|
||||
|
||||
## PCB
|
||||

|
68
usermods/Enclosure_with_OLED_temp_ESP07/readme.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Almost universal controller board for outdoor applications
|
||||
This usermod is using ideas from @mrVanboy and @400killer
|
||||
|
||||
Installation of file: Copy and replace file in wled00 directory.
|
||||
|
||||
For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
|
||||
|
||||
## Project repository
|
||||
- [Original repository](https://github.com/srg74/Controller-for-WLED-firmware) - Main controller repository
|
||||
## Features
|
||||
- SSD1306 128x32 and 128x64 I2C OLED display
|
||||
- On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
|
||||
- Auto display shutoff for saving display lifetime
|
||||
- Dallas temperature sensor
|
||||
- Reporting temperature to MQTT broker
|
||||
|
||||
## Hardware
|
||||

|
||||
|
||||
## Functionality checked with
|
||||
- ESP-07S
|
||||
- PlatformIO
|
||||
- SSD1306 128x32 I2C OLED display
|
||||
- DS18B20 (temperature sensor)
|
||||
- BME280 (temperature, humidity and pressure sensor)
|
||||
- KY-022 (infrared receiver)
|
||||
- Push button (N.O. momentary switch)
|
||||
|
||||
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
||||
|
||||
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For BME280 sensor uncomment following
|
||||
BME280@~3.0.0
|
||||
...
|
||||
```
|
209
usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <DallasTemperature.h> //Dallastemperature sensor
|
||||
//The SCL and SDA pins are defined here.
|
||||
//Lolin32 boards use SCL=5 SDA=4
|
||||
#define U8X8_PIN_SCL 5
|
||||
#define U8X8_PIN_SDA 4
|
||||
// Dallas sensor
|
||||
OneWire oneWire(13);
|
||||
DallasTemperature sensor(&oneWire);
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// gets called once at boot. Do all initialization that doesn't depend on
|
||||
// network here
|
||||
void userSetup() {
|
||||
sensor.begin(); //Start Dallas temperature sensor
|
||||
u8x8.begin();
|
||||
//u8x8.setFlipMode(1); //Uncoment if using WLED Wemos shield
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
//----> Dallas temperature sensor MQTT publishing
|
||||
temptimer = millis();
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = temptimer;
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
sensor.requestTemperatures();
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
float board_temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
float board_temperature = sensor.getTempFByIndex(0);
|
||||
#endif
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(board_temperature).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
266
usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <Wire.h>
|
||||
#include <BME280I2C.h> //BME280 sensor
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
// BME280 sensor timer
|
||||
long tempTimer = millis();
|
||||
long lastMeasure = 0;
|
||||
|
||||
float SensorPressure(NAN);
|
||||
float SensorTemperature(NAN);
|
||||
float SensorHumidity(NAN);
|
||||
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
Wire.begin(SDA_PIN,SCL_PIN);
|
||||
|
||||
while(!bme.begin())
|
||||
{
|
||||
Serial.println("Could not find BME280I2C sensor!");
|
||||
delay(1000);
|
||||
}
|
||||
switch(bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
Serial.println("Found BME280 sensor! Success.");
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
Serial.println("Found BMP280 sensor! No Humidity available.");
|
||||
break;
|
||||
default:
|
||||
Serial.println("Found UNKNOWN sensor! Error!");
|
||||
}
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// BME280 sensor MQTT publishing
|
||||
tempTimer = millis();
|
||||
// Timer to publish new sensor data every 60 seconds
|
||||
if (tempTimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = tempTimer;
|
||||
|
||||
// Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
UpdateBME280Data();
|
||||
float board_temperature = SensorTemperature;
|
||||
float board_pressure = SensorPressure;
|
||||
float board_humidity = SensorHumidity;
|
||||
|
||||
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
String p = String(mqttDeviceTopic);
|
||||
p += "/pressure";
|
||||
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
|
||||
String h = String(mqttDeviceTopic);
|
||||
h += "/humidity";
|
||||
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
|
||||
void UpdateBME280Data() {
|
||||
float temp(NAN), hum(NAN), pres(NAN);
|
||||
#ifdef Celsius
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
||||
#else
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
||||
#endif
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
SensorTemperature=temp;
|
||||
SensorHumidity=hum;
|
||||
SensorPressure=pres;
|
||||
}
|
54
usermods/Fix_unreachable_netservices_v2/readme.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Fix unreachable net services V2
|
||||
|
||||
This usermod-v2 modification performs a ping request to the local IP address every 60 seconds. By this procedure the net services of WLED remains accessible in some problematic WLAN environments.
|
||||
|
||||
The modification works with static or DHCP IP address configuration.
|
||||
|
||||
**Webinterface**: The number of pings and reconnects is displayed on the info page in the web interface.
|
||||
|
||||
_Story:_
|
||||
|
||||
Unfortunately, with all ESP projects where a web server or other network services are running, I have the problem that after some time the web server is no longer accessible. Now I found out that the connection is at least reestablished when a ping request is executed by the device.
|
||||
|
||||
With this modification, in the worst case, the network functions are not available for 60 seconds until the next ping request.
|
||||
|
||||
## Installation
|
||||
|
||||
1. Copy the file `usermod_Fix_unreachable_netservices.h` to the `wled00` directory.
|
||||
2. Register the usermod by adding `#include "usermod_Fix_unreachable_netservices.h"` in the top and `registerUsermod(new FixUnreachableNetServices());` in the bottom of `usermods_list.cpp`.
|
||||
|
||||
Example **usermods_list.cpp**:
|
||||
|
||||
```cpp
|
||||
#include "wled.h"
|
||||
/*
|
||||
* Register your v2 usermods here!
|
||||
* (for v1 usermods using just usermod.cpp, you can ignore this file)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add/uncomment your usermod filename here (and once more below)
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//#include "usermod_v2_example.h"
|
||||
//#include "usermod_temperature.h"
|
||||
//#include "usermod_v2_empty.h"
|
||||
#include "usermod_Fix_unreachable_netservices.h"
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
* Add your usermod class name here
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
//usermods.add(new UsermodTemperature());
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
usermods.add(new FixUnreachableNetServices());
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Hopefully I can help someone with that - @gegu
|
@@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
#include <ping.h>
|
||||
|
||||
/*
|
||||
* This usermod performs a ping request to the local IP address every 60 seconds.
|
||||
* By this procedure the net services of WLED remains accessible in some problematic WLAN environments.
|
||||
*
|
||||
* Usermods allow you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
*
|
||||
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
|
||||
* Multiple v2 usermods can be added to one compilation easily.
|
||||
*
|
||||
* Creating a usermod:
|
||||
* This file serves as an example. If you want to create a usermod, it is recommended to use usermod_v2_empty.h from the usermods folder as a template.
|
||||
* Please remember to rename the class and file to a descriptive name.
|
||||
* You may also use multiple .h and .cpp files.
|
||||
*
|
||||
* Using a usermod:
|
||||
* 1. Copy the usermod into the sketch folder (same folder as wled00.ino)
|
||||
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||
*/
|
||||
|
||||
class FixUnreachableNetServices : public Usermod {
|
||||
private:
|
||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
unsigned long m_lastTime = 0;
|
||||
|
||||
// desclare required variables
|
||||
const unsigned int PingDelayMs = 60000;
|
||||
unsigned long m_connectedWiFi = 0;
|
||||
ping_option m_pingOpt;
|
||||
unsigned int m_pingCount = 0;
|
||||
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup() {
|
||||
//Serial.println("Hello from my usermod!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected() {
|
||||
//Serial.println("Connected to WiFi!");
|
||||
|
||||
++m_connectedWiFi;
|
||||
|
||||
// initialize ping_options structure
|
||||
memset(&m_pingOpt, 0, sizeof(struct ping_option));
|
||||
m_pingOpt.count = 1;
|
||||
m_pingOpt.ip = WiFi.localIP();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop() {
|
||||
if (m_connectedWiFi > 0 && millis()-m_lastTime > PingDelayMs)
|
||||
{
|
||||
ping_start(&m_pingOpt);
|
||||
m_lastTime = millis();
|
||||
++m_pingCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
//this code adds "u":{"⚡ Ping fix pings": m_pingCount} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray infoArr = user.createNestedArray("⚡ Ping fix pings"); //name
|
||||
infoArr.add(m_pingCount); //value
|
||||
|
||||
//this code adds "u":{"⚡ Reconnects": m_connectedWiFi - 1} to the info object
|
||||
infoArr = user.createNestedArray("⚡ Reconnects"); //name
|
||||
infoArr.add(m_connectedWiFi - 1); //value
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
*/
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_FIXNETSERVICES;
|
||||
}
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
17
usermods/Fix_unreachable_webserver/readme.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Fix unreachable Webserver
|
||||
|
||||
This modification performs a ping request to the local IP address every 60 seconds. By this procedure the web server remains accessible in some problematic WLAN environments.
|
||||
|
||||
The modification works with static or DHCP IP address configuration
|
||||
|
||||
_Story:_
|
||||
|
||||
Unfortunately, with all ESP projects where a web server or other network services are running, I have the problem that after some time the web server is no longer accessible. Now I found out that the connection is at least reestablished when a ping request is executed by the device.
|
||||
|
||||
With this modification, in the worst case, the network functions are not available for 60 seconds until the next ping request.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy and replace the file `usermod.cpp` in wled00 directory.
|
||||
|
||||
|
43
usermods/Fix_unreachable_webserver/usermod.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
#include <ping.h>
|
||||
|
||||
const int PingDelayMs = 60000;
|
||||
long lastCheckTime = 0;
|
||||
bool connectedWiFi = false;
|
||||
ping_option pingOpt;
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
connectedWiFi = true;
|
||||
// initialize ping_options structure
|
||||
memset(&pingOpt, 0, sizeof(struct ping_option));
|
||||
pingOpt.count = 1;
|
||||
pingOpt.ip = WiFi.localIP();
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
if (connectedWiFi && millis()-lastCheckTime > PingDelayMs)
|
||||
{
|
||||
ping_start(&pingOpt);
|
||||
lastCheckTime = millis();
|
||||
}
|
||||
}
|
9
usermods/PIR_sensor_mqtt_v1/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# PIR sensor with MQTT
|
||||
|
||||
This simple usermod allows attaching a PIR sensor like the AM312 and publish the readings over MQTT. A message is sent when motion is detected as well as when motion has stopped.
|
||||
|
||||
This usermod has only been tested with the AM312 sensor though should work for any other PIR sensor. Note that this does not control the LED strip directly, it only publishes MQTT readings for use with other integrations like Home Assistant.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy and replace the file `usermod.cpp` in wled00 directory.
|
55
usermods/PIR_sensor_mqtt_v1/usermod.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This v1 usermod file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
|
||||
*
|
||||
* Consider the v2 usermod API if you need a more advanced feature set!
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
// PIR sensor pin
|
||||
const int MOTION_PIN = 16;
|
||||
// MQTT topic for sensor values
|
||||
const char MQTT_TOPIC[] = "/motion";
|
||||
|
||||
int prevState = LOW;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
pinMode(MOTION_PIN, INPUT);
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void publishMqtt(String state)
|
||||
{
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr){
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, MQTT_TOPIC);
|
||||
mqtt->publish(subuf, 0, true, state.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
if (digitalRead(MOTION_PIN) == HIGH && prevState == LOW) { // Motion detected
|
||||
publishMqtt("ON");
|
||||
prevState = HIGH;
|
||||
}
|
||||
if (digitalRead(MOTION_PIN) == LOW && prevState == HIGH) { // Motion stopped
|
||||
publishMqtt("OFF");
|
||||
prevState = LOW;
|
||||
}
|
||||
}
|
||||
|
75
usermods/PIR_sensor_switch/readme.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# PIR sensor switch
|
||||
|
||||
This usermod-v2 modification allows the connection of a PIR sensor to switch on the LED strip when motion is detected. The switch-off occurs ten minutes after no more motion is detected.
|
||||
|
||||
_Story:_
|
||||
|
||||
I use the PIR Sensor to automatically turn on the WLED analog clock in my home office room when I am there.
|
||||
The LED strip is switched [using a relay](https://github.com/Aircoookie/WLED/wiki/Control-a-relay-with-WLED) to keep the power consumption low when it is switched off.
|
||||
|
||||
## Webinterface
|
||||
|
||||
The info page in the web interface shows the items below
|
||||
|
||||
- the state of the sensor. By clicking on the state the sensor can be deactivated/activated.
|
||||
**I recommend to deactivate the sensor before installing an OTA update**.
|
||||
- the remaining time of the off timer.
|
||||
|
||||
## JSON API
|
||||
|
||||
The usermod supports the following state changes:
|
||||
|
||||
| JSON key | Value range | Description |
|
||||
|------------|-------------|---------------------------------|
|
||||
| PIRenabled | bool | Deactivdate/activate the sensor |
|
||||
| PIRoffSec | 60 to 43200 | Off timer seconds |
|
||||
|
||||
## Sensor connection
|
||||
|
||||
My setup uses an HC-SR501 sensor, a HC-SR505 should also work.
|
||||
|
||||
The usermod uses GPIO13 (D1 mini pin D7) for the sensor signal.
|
||||
[This example page](http://www.esp8266learning.com/wemos-mini-pir-sensor-example.php) describes how to connect the sensor.
|
||||
|
||||
Use the potentiometers on the sensor to set the time-delay to the minimum and the sensitivity to about half, or slightly above.
|
||||
|
||||
## Usermod installation
|
||||
|
||||
1. Copy the file `usermod_PIR_sensor_switch.h` to the `wled00` directory.
|
||||
2. Register the usermod by adding `#include "usermod_PIR_sensor_switch.h"` in the top and `registerUsermod(new PIRsensorSwitch());` in the bottom of `usermods_list.cpp`.
|
||||
|
||||
Example **usermods_list.cpp**:
|
||||
|
||||
```cpp
|
||||
#include "wled.h"
|
||||
/*
|
||||
* Register your v2 usermods here!
|
||||
* (for v1 usermods using just usermod.cpp, you can ignore this file)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add/uncomment your usermod filename here (and once more below)
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//#include "usermod_v2_example.h"
|
||||
//#include "usermod_temperature.h"
|
||||
//#include "usermod_v2_empty.h"
|
||||
#include "usermod_PIR_sensor_switch.h"
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
* Add your usermod class name here
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
//usermods.add(new UsermodTemperature());
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
usermods.add(new PIRsensorSwitch());
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Have fun - @gegu
|
249
usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
Normal file
@@ -0,0 +1,249 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* This usermod handles PIR sensor states.
|
||||
* The strip will be switched on and the off timer will be resetted when the sensor goes HIGH.
|
||||
* When the sensor state goes LOW, the off timer is started and when it expires, the strip is switched off.
|
||||
*
|
||||
*
|
||||
* Usermods allow you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
*
|
||||
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
|
||||
* Multiple v2 usermods can be added to one compilation easily.
|
||||
*
|
||||
* Creating a usermod:
|
||||
* This file serves as an example. If you want to create a usermod, it is recommended to use usermod_v2_empty.h from the usermods folder as a template.
|
||||
* Please remember to rename the class and file to a descriptive name.
|
||||
* You may also use multiple .h and .cpp files.
|
||||
*
|
||||
* Using a usermod:
|
||||
* 1. Copy the usermod into the sketch folder (same folder as wled00.ino)
|
||||
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||
*/
|
||||
|
||||
class PIRsensorSwitch : public Usermod {
|
||||
private:
|
||||
// PIR sensor pin
|
||||
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
|
||||
// notification mode for colorUpdated()
|
||||
const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE
|
||||
// delay before switch off after the sensor state goes LOW
|
||||
uint32_t m_switchOffDelay = 600000;
|
||||
// off timer start time
|
||||
uint32_t m_offTimerStart = 0;
|
||||
// current PIR sensor pin state
|
||||
byte m_PIRsensorPinState = LOW;
|
||||
// PIR sensor enabled - ISR attached
|
||||
bool m_PIRenabled = true;
|
||||
|
||||
/*
|
||||
* return or change if new PIR sensor state is available
|
||||
*/
|
||||
static volatile bool newPIRsensorState(bool changeState = false, bool newState = false) {
|
||||
static volatile bool s_PIRsensorState = false;
|
||||
if (changeState) {
|
||||
s_PIRsensorState = newState;
|
||||
}
|
||||
return s_PIRsensorState;
|
||||
}
|
||||
|
||||
/*
|
||||
* PIR sensor state has changed
|
||||
*/
|
||||
static void IRAM_ATTR ISR_PIRstateChange() {
|
||||
newPIRsensorState(true, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* switch strip on/off
|
||||
*/
|
||||
void switchStrip(bool switchOn) {
|
||||
if (switchOn && bri == 0) {
|
||||
bri = briLast;
|
||||
colorUpdated(NotifyUpdateMode);
|
||||
}
|
||||
else if (!switchOn && bri != 0) {
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
colorUpdated(NotifyUpdateMode);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read and update PIR sensor state.
|
||||
* Initilize/reset switch off timer
|
||||
*/
|
||||
bool updatePIRsensorState() {
|
||||
if (newPIRsensorState()) {
|
||||
m_PIRsensorPinState = digitalRead(PIRsensorPin);
|
||||
|
||||
if (m_PIRsensorPinState == HIGH) {
|
||||
m_offTimerStart = 0;
|
||||
switchStrip(true);
|
||||
}
|
||||
else if (bri != 0) {
|
||||
// start switch off timer
|
||||
m_offTimerStart = millis();
|
||||
}
|
||||
newPIRsensorState(true, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* switch off the strip if the delay has elapsed
|
||||
*/
|
||||
bool handleOffTimer() {
|
||||
if (m_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay) {
|
||||
switchStrip(false);
|
||||
m_offTimerStart = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup() {
|
||||
// PIR Sensor mode INPUT_PULLUP
|
||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||
// assign interrupt function and set CHANGE mode
|
||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*/
|
||||
void loop() {
|
||||
if (!updatePIRsensorState()) {
|
||||
handleOffTimer();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
*
|
||||
* Add PIR sensor state and switch off timer duration to jsoninfo
|
||||
*/
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
//this code adds "u":{"⏲ PIR sensor state":uiDomString} to the info object
|
||||
// the value contains a button to toggle the sensor enabled/disabled
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray infoArr = user.createNestedArray("⏲ PIR sensor state"); //name
|
||||
String uiDomString = "<button class=\"btn infobtn\" onclick=\"requestJson({PIRenabled:";
|
||||
String sensorStateInfo;
|
||||
|
||||
// PIR sensor state
|
||||
if (m_PIRenabled) {
|
||||
uiDomString += "false";
|
||||
sensorStateInfo = (m_PIRsensorPinState != LOW ? "active" : "inactive"); //value
|
||||
} else {
|
||||
uiDomString += "true";
|
||||
sensorStateInfo = "Disabled !";
|
||||
}
|
||||
uiDomString += "});return false;\">";
|
||||
uiDomString += sensorStateInfo;
|
||||
uiDomString += "</button>";
|
||||
infoArr.add(uiDomString); //value
|
||||
|
||||
//this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
|
||||
infoArr = user.createNestedArray("⏲ switch off timer"); //name
|
||||
|
||||
// off timer
|
||||
if (m_offTimerStart > 0) {
|
||||
uiDomString = "";
|
||||
unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000;
|
||||
if (offSeconds >= 3600) {
|
||||
uiDomString += (offSeconds / 3600);
|
||||
uiDomString += " hours ";
|
||||
offSeconds %= 3600;
|
||||
}
|
||||
if (offSeconds >= 60) {
|
||||
uiDomString += (offSeconds / 60);
|
||||
offSeconds %= 60;
|
||||
} else if (uiDomString.length() > 0){
|
||||
uiDomString += 0;
|
||||
}
|
||||
if (uiDomString.length() > 0){
|
||||
uiDomString += " min ";
|
||||
}
|
||||
uiDomString += (offSeconds);
|
||||
infoArr.add(uiDomString + " sec");
|
||||
} else {
|
||||
infoArr.add("inactive");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
* Add "PIRenabled" to json state. This can be used to disable/enable the sensor.
|
||||
* Add "PIRoffSec" to json state. This can be used to adjust <m_switchOffDelay> milliseconds .
|
||||
*/
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
root["PIRenabled"] = m_PIRenabled;
|
||||
root["PIRoffSec"] = (m_switchOffDelay / 1000);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
* Read "PIRenabled" from json state and switch enable/disable the PIR sensor.
|
||||
* Read "PIRoffSec" from json state and adjust <m_switchOffDelay> milliseconds .
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
if (root["PIRoffSec"] != nullptr) {
|
||||
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root["PIRoffSec"].as<unsigned long>())));
|
||||
}
|
||||
|
||||
if (root["PIRenabled"] != nullptr) {
|
||||
if (root["PIRenabled"] && !m_PIRenabled) {
|
||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||
newPIRsensorState(true, true);
|
||||
}
|
||||
else if(m_PIRenabled) {
|
||||
detachInterrupt(PIRsensorPin);
|
||||
}
|
||||
m_PIRenabled = root["PIRenabled"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
*/
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_PIRSWITCH;
|
||||
}
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
34
usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# QuinLED Dig Uno board
|
||||
|
||||
These files allow WLED 0.9.1 to report the temp sensor on the Quinled board to MQTT. I use it to report the board temp to Home Assistant via MQTT, so it will send notifications if something happens and the board start to heat up.
|
||||
This code uses Aircookie's WLED software. It has a premade file for user modifications. I use it to publish the temperature from the dallas temperature sensor on the Quinled board. The entries for the top of the WLED00 file, initializes the required libraries, and variables for the sensor. The .ino file waits for 60 seconds, and checks to see if the MQTT server is connected (thanks Aircoookie). It then poles the sensor, and published it using the MQTT service already running, using the main topic programmed in the WLED UI.
|
||||
|
||||
Installation of file: Copy and replace file in wled00 directory
|
||||
|
||||
## Project link
|
||||
|
||||
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
|
||||
|
||||
### Platformio requirements
|
||||
|
||||
Uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
54
usermods/QuinLED_Dig_Uno_Temp_MQTT/usermod.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <Arduino.h>
|
||||
#include "wled.h"
|
||||
//Intiating code for QuinLED Dig-Uno temp sensor
|
||||
//Uncomment Celsius if that is your prefered temperature scale
|
||||
#include <DallasTemperature.h> //Dallastemperature sensor
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
OneWire oneWire(18);
|
||||
#else //ESP8266 boards
|
||||
OneWire oneWire(14);
|
||||
#endif
|
||||
DallasTemperature sensor(&oneWire);
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
void userSetup()
|
||||
{
|
||||
// Start the DS18B20 sensor
|
||||
sensor.begin();
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
temptimer = millis();
|
||||
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000) {
|
||||
lastMeasure = temptimer;
|
||||
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr){
|
||||
sensor.requestTemperatures();
|
||||
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
float board_temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
float board_temperature = sensors.getTempFByIndex(0);
|
||||
#endif
|
||||
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(board_temperature).c_str());
|
||||
return;}
|
||||
return;}
|
||||
return;
|
||||
}
|
77
usermods/TTGO-T-Display/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# TTGO T-Display ESP32 with 240x135 TFT via SPI with TFT_eSPI
|
||||
This usermod allows use of the TTGO T-Display ESP32 module with integrated 240x135 display
|
||||
for controlling WLED and showing the following information:
|
||||
* Current SSID
|
||||
* IP address if obtained
|
||||
* in AP mode and turned off lightning AP password is shown
|
||||
* Current effect
|
||||
* Current palette
|
||||
|
||||
Usermod based on a rework of the ssd1306_i2c_oled_u8g2 usermod from the WLED repo.
|
||||
|
||||
## Hardware
|
||||

|
||||
|
||||
## Github reference for TTGO-Tdisplay
|
||||
|
||||
* [TTGO T-Display](https://github.com/Xinyuan-LilyGO/TTGO-T-Display)
|
||||
|
||||
## Requirements
|
||||
Functionality checked with:
|
||||
* TTGO T-Display
|
||||
* PlatformIO
|
||||
* Group of 4 individual Neopixels from Adafruit, and a full string of 68 LEDs.
|
||||
|
||||
## Platformio Requirements
|
||||
### Platformio.ini changes
|
||||
Under the root folder of the project, in the `platformio.ini` file, uncomment the `TFT_eSPI` line within the [common] section, under `lib_deps`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps =
|
||||
...
|
||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||
#TFT_eSPI
|
||||
...
|
||||
```
|
||||
|
||||
Also, while in the `platformio.ini` file, you must change the environment setup to build for just the esp32dev platform as follows:
|
||||
|
||||
Comment out the line described below:
|
||||
```ini
|
||||
# Travis CI binaries (comment this out when building for single board)
|
||||
; default_envs = travis_esp8266, esp01, esp01_1m_ota, travis_esp32
|
||||
```
|
||||
and UNCOMMENT the following line in the 'Single binaries' section:
|
||||
```ini
|
||||
default_envs = esp32dev
|
||||
```
|
||||
Save the `platformio.ini` file. Once this is saved, the required library files should be automatically downloaded for modifications in a later step.
|
||||
|
||||
### Platformio_overrides.ini (added)
|
||||
Copy the `platformio_overrides.ini` file which is contained in the `usermods/TTGO-T-Display/` folder into the root of your project folder. This file contains an override that remaps the button pin of WLED to use the on-board button to the right of the USB-C connector (when viewed with the port oriented downward - see hardware photo).
|
||||
|
||||
### TFT_eSPI Library Adjustments (board selection)
|
||||
We need to modify a file in the `TFT_eSPI` library to select the correct board. If you followed the directions to modify and save the `platformio.ini` file above, the `User_Setup_Select.h` file can be found in the `/.pio/libdeps/esp32dev/TFT_eSPI_ID1559` folder.
|
||||
|
||||
Modify the `User_Setup_Select.h` file as follows:
|
||||
* Comment out the following line (which is the 'default' setup file):
|
||||
```ini
|
||||
//#include <User_Setup.h> // Default setup is root library folder
|
||||
```
|
||||
* Uncomment the following line (which points to the setup file for the TTGO T-Display):
|
||||
```ini
|
||||
#include <User_Setups/Setup25_TTGO_T_Display.h> // Setup file for ESP32 and TTGO T-Display ST7789V SPI bus TFT
|
||||
```
|
||||
|
||||
Run the build and it should complete correctly. If you see a failure like this:
|
||||
```ini
|
||||
xtensa-esp32-elf-g++: error: wled00\wled00.ino.cpp: No such file or directory
|
||||
xtensa-esp32-elf-g++: fatal error: no input files
|
||||
```
|
||||
Just try building again - I find that sometimes this happens on the first build attempt and subsequent attempts will build correctly.
|
||||
|
||||
## Arduino IDE
|
||||
- UNTESTED
|
BIN
usermods/TTGO-T-Display/assets/ttgo_hardware1.png
Normal file
After Width: | Height: | Size: 686 KiB |
8
usermods/TTGO-T-Display/platformio_override.ini
Normal file
@@ -0,0 +1,8 @@
|
||||
[env:esp32dev]
|
||||
build_flags = ${common.build_flags_esp32}
|
||||
; PIN defines - uncomment and change, if needed:
|
||||
; -D LEDPIN=2
|
||||
-D BTNPIN=35
|
||||
; -D IR_PIN=4
|
||||
; -D RLYPIN=12
|
||||
; -D RLYMDE=1
|
214
usermods/TTGO-T-Display/usermod.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pin 2 of the TTGO T-Display serves as the data line for the LED string.
|
||||
* Pin 35 is set up as the button pin in the platformio_overrides.ini file.
|
||||
* The button can be set up via the macros section in the web interface.
|
||||
* I use the button to cycle between presets.
|
||||
* The Pin 35 button is the one on the RIGHT side of the USB-C port on the board,
|
||||
* when the port is oriented downwards. See readme.md file for photo.
|
||||
* The display is set up to turn off after 5 minutes, and turns on automatically
|
||||
* when a change in the dipslayed info is detected (within a 5 second interval).
|
||||
*/
|
||||
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
#include "wled.h"
|
||||
#include <TFT_eSPI.h>
|
||||
#include <SPI.h>
|
||||
#include "WiFi.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#ifndef TFT_DISPOFF
|
||||
#define TFT_DISPOFF 0x28
|
||||
#endif
|
||||
|
||||
#ifndef TFT_SLPIN
|
||||
#define TFT_SLPIN 0x10
|
||||
#endif
|
||||
|
||||
#define TFT_MOSI 19
|
||||
#define TFT_SCLK 18
|
||||
#define TFT_CS 5
|
||||
#define TFT_DC 16
|
||||
#define TFT_RST 23
|
||||
|
||||
#define TFT_BL 4 // Display backlight control pin
|
||||
#define ADC_EN 14 // Used for enabling battery voltage measurements - not used in this program
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Start");
|
||||
tft.init();
|
||||
tft.setRotation(3); //Rotation here is set up for the text to be readable with the port on the left. Use 1 to flip.
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextSize(2);
|
||||
tft.setTextColor(TFT_WHITE);
|
||||
tft.setCursor(1, 10);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextSize(2);
|
||||
tft.print("Loading...");
|
||||
|
||||
if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
|
||||
pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
|
||||
digitalWrite(TFT_BL, HIGH); // Turn backlight on.
|
||||
}
|
||||
|
||||
// tft.setRotation(3);
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
uint8_t tftcharwidth = 19; // Number of chars that fit on screen with text size set to 2
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 5 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 5*60*1000) {
|
||||
digitalWrite(TFT_BL, LOW); // Turn backlight off.
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on.
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextSize(2);
|
||||
// First row with Wifi name
|
||||
tft.setCursor(1, 10);
|
||||
tft.print(knownSsid.substring(0, tftcharwidth > 1 ? tftcharwidth - 1 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than our dicplay
|
||||
if (knownSsid.length() > tftcharwidth)
|
||||
tft.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
tft.setCursor(1, 40);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
tft.print(apPass);
|
||||
else
|
||||
tft.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
tft.setCursor(1, 70);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
tft.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > tftcharwidth - 1))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
tft.setCursor(1, 100);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
tft.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
// The following is modified from the code from the u8g2/u8g8 based code (knownPalette was knownMode)
|
||||
if ((qComma > knownPalette) || (printedChars > tftcharwidth - 1))
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
40
usermods/Temperature/readme.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Temperature usermod
|
||||
|
||||
Based on the excellent `QuinLED_Dig_Uno_Temp_MQTT` by srg74 and 400killer!
|
||||
This usermod will read from an attached DS18B20 temperature sensor (as available on the QuinLED Dig-Uno)
|
||||
The temperature is displayed both in the Info section of the web UI as well as published to the `/temperature` MQTT topic if enabled.
|
||||
This usermod will be expanded with support for different sensor types in the future.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy `usermod_temperature.h` to the wled00 directory.
|
||||
Uncomment the corresponding lines in `usermods_list.cpp` and compile!
|
||||
If this is the only v2 usermod you plan to use, you can alternatively replace `usermods_list.h` in wled00 with the one in this folder.
|
||||
|
||||
## Project link
|
||||
|
||||
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
|
||||
|
||||
### PlatformIO requirements
|
||||
|
||||
You might have to uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
79
usermods/Temperature/usermod_temperature.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
#include <DallasTemperature.h> //DS18B20
|
||||
|
||||
//Pin defaults for QuinLed Dig-Uno
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define TEMPERATURE_PIN 18
|
||||
#else //ESP8266 boards
|
||||
#define TEMPERATURE_PIN 14
|
||||
#endif
|
||||
|
||||
#define TEMP_CELSIUS // Comment out for Fahrenheit
|
||||
|
||||
#define MEASUREMENT_INTERVAL 60000 //1 Minute
|
||||
|
||||
OneWire oneWire(TEMPERATURE_PIN);
|
||||
DallasTemperature sensor(&oneWire);
|
||||
|
||||
class UsermodTemperature : public Usermod {
|
||||
private:
|
||||
//set last reading as "40 sec before boot", so first reading is taken after 20 sec
|
||||
unsigned long lastMeasurement = UINT32_MAX - 40000;
|
||||
float temperature = 0.0f;
|
||||
public:
|
||||
void getReading() {
|
||||
sensor.requestTemperatures();
|
||||
#ifdef TEMP_CELSIUS
|
||||
temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
temperature = sensor.getTempFByIndex(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup() {
|
||||
sensor.begin();
|
||||
sensor.setResolution(9);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (millis() - lastMeasurement > MEASUREMENT_INTERVAL)
|
||||
{
|
||||
getReading();
|
||||
|
||||
if (WLED_MQTT_CONNECTED) {
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(temperature).c_str());
|
||||
}
|
||||
lastMeasurement = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void addToJsonInfo(JsonObject& root) {
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray temp = user.createNestedArray("Temperature");
|
||||
if (temperature == DEVICE_DISCONNECTED_C) {
|
||||
temp.add(0);
|
||||
temp.add(" Sensor Error!");
|
||||
return;
|
||||
}
|
||||
|
||||
temp.add(temperature);
|
||||
#ifdef TEMP_CELSIUS
|
||||
temp.add("°C");
|
||||
#else
|
||||
temp.add("°F");
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_TEMPERATURE;
|
||||
}
|
||||
};
|
25
usermods/Temperature/usermods_list.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* Register your v2 usermods here!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add/uncomment your usermod filename here (and once more below)
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//#include "usermod_v2_example.h"
|
||||
#include "usermod_temperature.h"
|
||||
//#include "usermod_v2_empty.h"
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
* Add your usermod class name here
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
usermods.add(new UsermodTemperature());
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
}
|
15
usermods/UserModv2_SunRiseAndSet/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
WLED v2 UserMod for running macros at sunrise and sunset.
|
||||
|
||||
At the time of this text, this user mod requires code to be changed to set certain variables:
|
||||
1. To reflect the user's graphical location (latitude/longitude) used for calculating apparent sunrise/sunset
|
||||
2. To specify which macros will be run at sunrise and/or sunset. (defaults to 15 at sunrise and 16 at sunset)
|
||||
3. To optionally provide an offset from sunrise/sunset, in minutes (max of +/- 2 hours), when the macro will be run.
|
||||
|
||||
In addition, WLED must be configured to get time from NTP (and the time must be retrieved via NTP.)
|
||||
|
||||
Please open the UserMod_SunRiseAndSet.h file for instructions on what needs to be changed, where to copy files, etc.
|
||||
|
||||
If this usermod proves useful enough, the code might eventually be updated to allow prompting for the required information
|
||||
via the web interface and to store settings in EEPROM instead of hard-coding in the .h file.
|
||||
|
||||
This usermod has only been tested on the esp32dev platform, but there's no reason it wouldn't work on other platforms.
|
166
usermods/UserModv2_SunRiseAndSet/UserMod_SunRiseAndSet.h
Normal file
@@ -0,0 +1,166 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
#include <Dusk2Dawn.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* REQUIREMENTS:
|
||||
* The Dusk2Dawn library must be installed. This can be found at https://github.com/dmkishi/Dusk2Dawn. The 1.0.1 version of this library found via
|
||||
* Arduino or platformio library managers is buggy and won't compile. The latest version from github should be used.
|
||||
*
|
||||
* NTP must be enabled and functional. It simply makes no sense to have events on sunrise/sunset when an accurate time isn't available.
|
||||
*
|
||||
* The user's geographical latitude and longitude must be configured (in decimal, not degrees/minutes/etc) using m_fLatitude and m_fLongitude
|
||||
*
|
||||
* if desired, an offset of up to +/- 2 hours can be specified for each of sunrise/sunset using m_sunriseOffset and m_sunsetOffset (defaults to 0)
|
||||
*
|
||||
* The specific macro to run at sunrise and/or sunset can be changed using m_sunriseMacro and m_sunsetMacro. (defaults to 15 and 16)
|
||||
*
|
||||
* From the Dusk2Dawn library:
|
||||
* HINT: An easy way to find the longitude and latitude for any location is
|
||||
* to find the spot in Google Maps, right click the place on the map, and
|
||||
* select "What's here?". At the bottom, you’ll see a card with the
|
||||
* coordinates.
|
||||
*
|
||||
* Once configured, copy UserMod_SunRiseAndSet.h to the sketch file (the same folder as wled00.ino exists),
|
||||
* and then edit "usermods_list.cpp":
|
||||
* Add '#include "UserMod_SunRiseAndSet.h"' in the 'includes' area
|
||||
* Add 'usermods.add(new UserMod_SunRiseAndSet());' in the registerUsermods() area
|
||||
*
|
||||
*/
|
||||
|
||||
class UserMod_SunRiseAndSet : public Usermod
|
||||
{
|
||||
private:
|
||||
|
||||
/**** USER SETTINGS ****/
|
||||
|
||||
float m_fLatitude = 40.6; // latitude where sunrise/set are calculated
|
||||
float m_fLongitude = -79.80; // longitude where sunrise/set are calculated
|
||||
int8_t m_sunriseOffset = 0; // offset from sunrise, in minutes, when macro should be run (negative for before sunrise, positive for after sunrise)
|
||||
int8_t m_sunsetOffset = 0; // offset from sunset, in minutes, when macro should be run (negative for before sunset, positive for after sunset)
|
||||
uint8_t m_sunriseMacro = 15; // macro number to run at sunrise
|
||||
uint8_t m_sunsetMacro = 16; // macro number to run at sunset
|
||||
|
||||
/**** END OF USER SETTINGS. DO NOT EDIT BELOW THIS LINE! ****/
|
||||
|
||||
|
||||
Dusk2Dawn *m_pD2D = NULL; // this must be dynamically allocated in order for parameters to be loaded from EEPROM
|
||||
|
||||
int m_nUserSunrise = -1; // time, in minutes from midnight, of sunrise
|
||||
int m_nUserSunset = -1; // time, in minutes from midnight, of sunset
|
||||
|
||||
byte m_nLastRunMinute = -1; // indicates what minute the userloop was last run - used so that the code only runs once per minute
|
||||
|
||||
public:
|
||||
|
||||
virtual void setup(void)
|
||||
{
|
||||
/* TODO: From EEPROM, load the following variables:
|
||||
*
|
||||
* int16_t latitude16 = 4060; // user provided latitude, multiplied by 100 and rounded
|
||||
* int16_t longitude16 = -7980; // user provided longitude, multiplied by 100 and rounded.
|
||||
* int8_t sunrise_offset = 0; // number of minutes to offset the sunrise macro trigger (positive for minutes after sunrise, negative for minutes before)
|
||||
* int8_t sunset_offset = 0; // number of minutes to offset the sunset macro trigger (positive for minutes after sunset, negative for minutes before)
|
||||
*
|
||||
* then:
|
||||
* m_fLatitude = (float)latitude / 100.0;
|
||||
* m_fLongitude = (float)longitude / 100.0;
|
||||
* m_sunriseOffset = sunrise_offset;
|
||||
* m_sunsetOffset = sunset_offset;
|
||||
*/
|
||||
|
||||
if ((0.0 != m_fLatitude) || (0.0 != m_fLongitude))
|
||||
{
|
||||
m_pD2D = new Dusk2Dawn (m_fLatitude, m_fLongitude, 0 /* UTC */);
|
||||
// can't really check for failures. if the alloc fails, the mod just doesn't work.
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// without NTP, or a configured lat/long, none of this stuff is going to work...
|
||||
// As an alternative, need to figure out how to determine if the user has manually set the clock or not.
|
||||
if (m_pD2D && (999000000L != ntpLastSyncTime))
|
||||
{
|
||||
// to prevent needing to import all the timezone stuff from other modules, work completely in UTC
|
||||
time_t timeUTC = now();
|
||||
tmElements_t tmNow;
|
||||
breakTime(timeUTC, tmNow);
|
||||
int nCurMinute = tmNow.Minute;
|
||||
|
||||
if (m_nLastRunMinute != nCurMinute) //only check once a new minute begins
|
||||
{
|
||||
m_nLastRunMinute = nCurMinute;
|
||||
int numMinutes = (60 * tmNow.Hour) + m_nLastRunMinute; // how many minutes into the day are we?
|
||||
|
||||
// check to see if sunrise/sunset should be re-determined. Only do this if neither sunrise nor sunset
|
||||
// are set. That happens when the device has just stated, and after both sunrise/sunset have already run.
|
||||
if ((-1 == m_nUserSunrise) && (-1 == m_nUserSunset))
|
||||
{
|
||||
m_nUserSunrise = m_pD2D->sunrise(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
|
||||
m_nUserSunset = m_pD2D->sunset(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
|
||||
if (m_nUserSunrise > numMinutes) // has sunrise already passed? if so, recompute for tomorrow
|
||||
{
|
||||
breakTime(timeUTC + (60*60*24), tmNow);
|
||||
m_nUserSunrise = m_pD2D->sunrise(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
|
||||
if (m_nUserSunset > numMinutes) // if sunset has also passed, recompute that as well
|
||||
{
|
||||
m_nUserSunset = m_pD2D->sunset(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
|
||||
}
|
||||
}
|
||||
// offset by user provided values. becuase the offsets are signed bytes, the max offset is just over 2 hours.
|
||||
m_nUserSunrise += m_sunriseOffset;
|
||||
m_nUserSunset += m_sunsetOffset;
|
||||
}
|
||||
|
||||
if (numMinutes == m_nUserSunrise) // Good Morning!
|
||||
{
|
||||
if (m_sunriseMacro)
|
||||
applyMacro(m_sunriseMacro); // run macro 15
|
||||
m_nUserSunrise = -1;
|
||||
}
|
||||
else if (numMinutes == m_nUserSunset) // Good Night!
|
||||
{
|
||||
if (m_sunsetMacro)
|
||||
applyMacro(m_sunsetMacro); // run macro 16
|
||||
m_nUserSunset = -1;
|
||||
}
|
||||
} // if (m_nLastRunMinute != nCurMinute)
|
||||
} // if (m_pD2D && (999000000L != ntpLastSyncTime))
|
||||
}
|
||||
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
JsonObject user = root["SunRiseAndSet"];
|
||||
if (user.isNull()) user = root.createNestedObject("SunRiseAndSet");
|
||||
|
||||
char buf[10];
|
||||
if (-1 != m_nUserSunrise)
|
||||
{
|
||||
snprintf(buf, 10, "%02d:%02d UTC", m_nUserSunrise / 60, m_nUserSunrise % 60);
|
||||
user["rise"] = buf;
|
||||
}
|
||||
if (-1 != m_nUserSunset)
|
||||
{
|
||||
snprintf(buf, 10, "%02d:%02d UTC", m_nUserSunset / 60, m_nUserSunset % 60);
|
||||
user["set"] = buf;
|
||||
}
|
||||
JsonObject vars = user.createNestedObject("vars");
|
||||
vars["lat"] = m_fLatitude;
|
||||
vars["long"] = m_fLongitude;
|
||||
vars["rise_mac"] = m_sunriseMacro;
|
||||
vars["set_mac"] = m_sunsetMacro;
|
||||
vars["rise_off"] = m_sunriseOffset;
|
||||
vars["set_off"] = m_sunsetOffset;
|
||||
}
|
||||
|
||||
~UserMod_SunRiseAndSet(void)
|
||||
{
|
||||
if (m_pD2D) delete m_pD2D;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
71
usermods/Wemos_D1_mini+Wemos32_mini_shield/readme.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Wemos D1 mini and Wemos32 mini shield
|
||||
- Installation of file: Copy and replace file in wled00 directory
|
||||
- For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
|
||||
- Added third choice of controller Heltec WiFi-Kit-8. Totally DIY but with OLED display.
|
||||
## Project repository
|
||||
- [Original repository](https://github.com/srg74/WLED-wemos-shield) - WLED Wemos shield repository
|
||||
- [Wemos shield project Wiki](https://github.com/srg74/WLED-wemos-shield/wiki)
|
||||
- [Precompiled WLED firmware](https://github.com/srg74/WLED-wemos-shield/tree/master/resources/Firmware)
|
||||
## Features
|
||||
- SSD1306 128x32 or 128x64 I2C OLED display
|
||||
- On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
|
||||
- Auto display shutoff for saving display lifetime
|
||||
- Dallas temperature sensor
|
||||
- Reporting temperature to MQTT broker
|
||||
- Relay for energy saving
|
||||
|
||||
## Hardware
|
||||

|
||||
|
||||
## Functionality checked with
|
||||
|
||||
- Wemos D1 mini original v3.1 and clones
|
||||
- Wemos32 mini
|
||||
- PlatformIO
|
||||
- SSD1306 128x32 I2C OLED display
|
||||
- DS18B20 (temperature sensor)
|
||||
- BME280 (temperature, humidity and pressure sensor)
|
||||
- Push button (N.O. momentary switch)
|
||||
|
||||
### Platformio requirements
|
||||
|
||||
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
||||
|
||||
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For BME280 sensor uncomment following
|
||||
BME280@~3.0.0
|
||||
...
|
||||
```
|
246
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <OneWire.h> // Dallas temperature sensor
|
||||
|
||||
//Dallas sensor quick reading. Credit to - Author: Peter Scargill, August 17th, 2013
|
||||
int16_t Dallas(int x, byte start)
|
||||
{
|
||||
OneWire DallasSensor(x);
|
||||
byte i;
|
||||
byte data[2];
|
||||
int16_t result;
|
||||
do
|
||||
{
|
||||
DallasSensor.reset();
|
||||
DallasSensor.write(0xCC);
|
||||
DallasSensor.write(0xBE);
|
||||
for ( i = 0; i < 2; i++) data[i] = DallasSensor.read();
|
||||
result=(data[1]<<8)|data[0];
|
||||
result>>=4; if (data[1]&128) result|=61440;
|
||||
if (data[0]&8) ++result;
|
||||
DallasSensor.reset();
|
||||
DallasSensor.write(0xCC);
|
||||
DallasSensor.write(0x44,1);
|
||||
if (start) delay(1000);
|
||||
} while (start--);
|
||||
return result;
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
uint8_t DALLAS_PIN =23;
|
||||
#else
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
uint8_t DALLAS_PIN =13;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// Dallas sensor reading timer
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
//Serial.begin(115200);
|
||||
|
||||
Dallas (DALLAS_PIN,1);
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
//----> Dallas temperature sensor MQTT publishing
|
||||
temptimer = millis();
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = temptimer;
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
// Serial.println(Dallas(DALLAS_PIN,0));
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
int16_t board_temperature = Dallas(DALLAS_PIN,0);
|
||||
#else
|
||||
int16_t board_temperature = (Dallas(DALLAS_PIN,0)* 1.8 + 32);
|
||||
#endif
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
knownSsid = WiFi.SSID();
|
||||
#else
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
268
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <Wire.h>
|
||||
#include <BME280I2C.h> //BME280 sensor
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
// BME280 sensor timer
|
||||
long tempTimer = millis();
|
||||
long lastMeasure = 0;
|
||||
|
||||
float SensorPressure(NAN);
|
||||
float SensorTemperature(NAN);
|
||||
float SensorHumidity(NAN);
|
||||
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
Wire.begin(SDA_PIN,SCL_PIN);
|
||||
|
||||
while(!bme.begin())
|
||||
{
|
||||
Serial.println("Could not find BME280I2C sensor!");
|
||||
delay(1000);
|
||||
}
|
||||
switch(bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
Serial.println("Found BME280 sensor! Success.");
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
Serial.println("Found BMP280 sensor! No Humidity available.");
|
||||
break;
|
||||
default:
|
||||
Serial.println("Found UNKNOWN sensor! Error!");
|
||||
}
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// BME280 sensor MQTT publishing
|
||||
tempTimer = millis();
|
||||
// Timer to publish new sensor data every 60 seconds
|
||||
if (tempTimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = tempTimer;
|
||||
|
||||
// Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
UpdateBME280Data();
|
||||
float board_temperature = SensorTemperature;
|
||||
float board_pressure = SensorPressure;
|
||||
float board_humidity = SensorHumidity;
|
||||
|
||||
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
String p = String(mqttDeviceTopic);
|
||||
p += "/pressure";
|
||||
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
|
||||
String h = String(mqttDeviceTopic);
|
||||
h += "/humidity";
|
||||
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
|
||||
void UpdateBME280Data() {
|
||||
float temp(NAN), hum(NAN), pres(NAN);
|
||||
#ifdef Celsius
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
#else
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
#endif
|
||||
SensorTemperature=temp;
|
||||
SensorHumidity=hum;
|
||||
SensorPressure=pres;
|
||||
}
|
12
usermods/battery_keypad_controller/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Battery powered controller with keypad
|
||||
|
||||
I'm using this controller for a festival totem. Runs on 3 18650 Cells, can deliver >5A current.
|
||||
|
||||
Via keypad one can select 8 presets, change effect, effect speed, effect intensity and palette. Brightness can be
|
||||
adjusted with a potentiometer.
|
||||
|
||||
## Pictures
|
||||
|
||||

|
||||

|
||||

|
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg
Normal file
After Width: | Height: | Size: 319 KiB |
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg
Normal file
After Width: | Height: | Size: 250 KiB |
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg
Normal file
After Width: | Height: | Size: 344 KiB |
151
usermods/battery_keypad_controller/wled06_usermod.ino
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* WLED usermod for keypad and brightness-pot.
|
||||
* 3'2020 https://github.com/hobbyquaker
|
||||
*/
|
||||
|
||||
#include <Keypad.h>
|
||||
const byte keypad_rows = 4;
|
||||
const byte keypad_cols = 4;
|
||||
char keypad_keys[keypad_rows][keypad_cols] = {
|
||||
{'1', '2', '3', 'A'},
|
||||
{'4', '5', '6', 'B'},
|
||||
{'7', '8', '9', 'C'},
|
||||
{'*', '0', '#', 'D'}
|
||||
};
|
||||
|
||||
byte keypad_colPins[keypad_rows] = {D3, D2, D1, D0};
|
||||
byte keypad_rowPins[keypad_cols] = {D7, D6, D5, D4};
|
||||
|
||||
Keypad myKeypad = Keypad(makeKeymap(keypad_keys), keypad_rowPins, keypad_colPins, keypad_rows, keypad_cols);
|
||||
|
||||
void userSetup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
long lastTime = 0;
|
||||
int delayMs = 20; //we want to do something every 2 seconds
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
if (millis()-lastTime > delayMs)
|
||||
{
|
||||
|
||||
long analog = analogRead(0);
|
||||
int new_bri = 1;
|
||||
if (analog > 900) {
|
||||
new_bri = 255;
|
||||
} else if (analog > 30) {
|
||||
new_bri = dim8_video(map(analog, 31, 900, 16, 255));
|
||||
}
|
||||
if (bri != new_bri) {
|
||||
bri = new_bri;
|
||||
colorUpdated(1);
|
||||
|
||||
}
|
||||
|
||||
char myKey = myKeypad.getKey();
|
||||
if (myKey != NULL) {
|
||||
switch (myKey) {
|
||||
case '1':
|
||||
applyPreset(1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '2':
|
||||
applyPreset(2);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '3':
|
||||
applyPreset(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '4':
|
||||
applyPreset(4);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '5':
|
||||
applyPreset(5);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '6':
|
||||
applyPreset(6);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'A':
|
||||
applyPreset(7);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'B':
|
||||
applyPreset(8);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '7':
|
||||
effectCurrent += 1;
|
||||
if (effectCurrent >= MODE_COUNT) effectCurrent = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '*':
|
||||
effectCurrent -= 1;
|
||||
if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '8':
|
||||
if (effectSpeed < 240) {
|
||||
effectSpeed += 12;
|
||||
} else if (effectSpeed < 255) {
|
||||
effectSpeed += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '0':
|
||||
if (effectSpeed > 15) {
|
||||
effectSpeed -= 12;
|
||||
} else if (effectSpeed > 0) {
|
||||
effectSpeed -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '9':
|
||||
if (effectIntensity < 240) {
|
||||
effectIntensity += 12;
|
||||
} else if (effectIntensity < 255) {
|
||||
effectIntensity += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '#':
|
||||
if (effectIntensity > 15) {
|
||||
effectIntensity -= 12;
|
||||
} else if (effectIntensity > 0) {
|
||||
effectIntensity -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
effectPalette += 1;
|
||||
if (effectPalette >= 50) effectPalette = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'D':
|
||||
effectPalette -= 1;
|
||||
if (effectPalette <= 0) effectPalette = 50;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lastTime = millis();
|
||||
}
|
||||
|
||||
}
|
28
usermods/blynk_relay_control/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Blynk controllable relay
|
||||
This usermod allows controlling a relay state from the user variables. It also allows the user variables to be set over Blynk.
|
||||
|
||||
Optionally, the servo can have a reset timer to go back to it's default state after an interval. This interval is set through userVar1.
|
||||
|
||||
## Instalation
|
||||
|
||||
Replace the WLED06_usermod.ino file in Aircoookies WLED folder with the one here.
|
||||
|
||||
## Customizations
|
||||
|
||||
Update the following parameters in WLED06_usermod.ino to configure the mod's behavior:
|
||||
|
||||
```cpp
|
||||
//Which pin is the relay connected to
|
||||
#define RELAY_PIN 5
|
||||
//Which pin state should the relay default to
|
||||
#define RELAY_PIN_DEFAULT LOW
|
||||
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
|
||||
#define RELAY_PIN_TIMER_DEFAULT 3000
|
||||
|
||||
//Blynk virtual pin for controlling relay
|
||||
#define BLYNK_USER_VAR0_PIN V9
|
||||
//Blynk virtual pin for controlling relay timer
|
||||
#define BLYNK_USER_VAR1_PIN V10
|
||||
//Number of milliseconds between updating blynk
|
||||
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
|
||||
```
|
96
usermods/blynk_relay_control/wled06_usermod.ino
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 (API calls &U0=, uint16_t) to set relay state
|
||||
#define relayPinState userVar0
|
||||
//Use userVar1 (API calls &U1=, uint16_t) to set relay timer duration
|
||||
//Ignored if 0, otherwise number of milliseconds to allow relay to stay in
|
||||
//non default state.
|
||||
#define relayTimerInterval userVar1
|
||||
|
||||
//Which pin is the relay connected to
|
||||
#define RELAY_PIN 5
|
||||
//Which pin state should the relay default to
|
||||
#define RELAY_PIN_DEFAULT LOW
|
||||
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
|
||||
#define RELAY_PIN_TIMER_DEFAULT 3000
|
||||
|
||||
//Blynk virtual pin for controlling relay
|
||||
#define BLYNK_USER_VAR0_PIN V9
|
||||
//Blynk virtual pin for controlling relay timer
|
||||
#define BLYNK_USER_VAR1_PIN V10
|
||||
//Number of milliseconds between updating blynk
|
||||
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
|
||||
|
||||
//Is the timer for resetting the relay active
|
||||
bool relayTimerStarted = false;
|
||||
//millis() time after which relay will be reset
|
||||
unsigned long relayTimeToDefault = 0;
|
||||
//millis() time after which relay vars in Blynk will be sent
|
||||
unsigned long relayBlynkUpdateTime = 0;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
relayTimerInterval = RELAY_PIN_TIMER_DEFAULT;
|
||||
pinMode(RELAY_PIN, OUTPUT);
|
||||
digitalWrite(RELAY_PIN, relayPinState);
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
//Normalize relayPinState to an accepted value
|
||||
if (relayPinState != HIGH && relayPinState != LOW) {
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
}
|
||||
//If relay changes and relayTimerInterval is set, start a timer to change back
|
||||
if (relayTimerInterval != 0 &&
|
||||
relayPinState != RELAY_PIN_DEFAULT &&
|
||||
!relayTimerStarted ) {
|
||||
relayTimerStarted = true;
|
||||
relayTimeToDefault = millis() + relayTimerInterval;
|
||||
}
|
||||
//If manually changed back to default, cancel timer
|
||||
if (relayTimerStarted && relayPinState == RELAY_PIN_DEFAULT ) {
|
||||
relayTimerStarted = false;
|
||||
}
|
||||
//If timer completes, set relay back to default
|
||||
if (relayTimerStarted && millis() > relayTimeToDefault) {
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
relayTimerStarted = false;
|
||||
}
|
||||
digitalWrite(RELAY_PIN, relayPinState);
|
||||
updateRelayBlynk();
|
||||
}
|
||||
|
||||
//Update Blynk with state of userVars at BLYNK_RELAY_UPDATE_INTERVAL
|
||||
void updateRelayBlynk()
|
||||
{
|
||||
if (!WLED_CONNECTED) return;
|
||||
if (relayBlynkUpdateTime > millis()) return;
|
||||
Blynk.virtualWrite(BLYNK_USER_VAR0_PIN, userVar0);
|
||||
Blynk.virtualWrite(BLYNK_USER_VAR1_PIN, userVar1);
|
||||
relayBlynkUpdateTime = millis() + BLYNK_RELAY_UPDATE_INTERVAL;
|
||||
}
|
||||
|
||||
//Add Blynk callback for setting userVar0
|
||||
BLYNK_WRITE(BLYNK_USER_VAR0_PIN)
|
||||
{
|
||||
userVar0 = param.asInt();
|
||||
}
|
||||
//Add Blynk callback for setting userVar1
|
||||
BLYNK_WRITE(BLYNK_USER_VAR1_PIN)
|
||||
{
|
||||
userVar1 = param.asInt();
|
||||
}
|
94
usermods/mpu6050_imu/readme.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# MPU-6050 Six-Axis (Gyro + Accelerometer) Driver
|
||||
|
||||
This usermod-v2 modification allows the connection of a MPU-6050 IMU sensor to
|
||||
allow for effects that are controlled by the orientation or motion of the WLED Device.
|
||||
|
||||
The MPU6050 has a built in "Digital Motion Processor" which does a lot of the heavy
|
||||
lifting in integrating the gyro and accel measurements to get potentially more
|
||||
useful gravity vector and orientation output.
|
||||
|
||||
It is pretty straightforward to comment out some of the variables being read off the device if they're not needed to save CPU/Mem/Bandwidth.
|
||||
|
||||
_Story:_
|
||||
|
||||
As a memento to a long trip I was on, I built an icosahedron globe. I put lights inside to indicate cities I travelled to.
|
||||
|
||||
I wanted to integrate an IMU to allow either on-board, or off-board effects that would
|
||||
react to the globes orientation. See the blog post on building it <https://www.robopenguins.com/icosahedron-travel-globe/> or a video demo <https://youtu.be/zYjybxHBsHM> .
|
||||
|
||||
## Adding Dependencies
|
||||
|
||||
I2Cdev and MPU6050 must be installed.
|
||||
|
||||
To install them, add I2Cdevlib-MPU6050@fbde122cc5 to lib_deps in the platformio.ini file.
|
||||
|
||||
You also need to change lib_compat_mode from strict to soft in platformio.ini (This ignores that I2Cdevlib-MPU6050 doesn't list platform compatibility)
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
lib_compat_mode = soft
|
||||
lib_deps =
|
||||
FastLED@3.3.2
|
||||
NeoPixelBus@2.5.7
|
||||
ESPAsyncTCP@1.2.0
|
||||
ESPAsyncUDP@697c75a025
|
||||
AsyncTCP@1.0.3
|
||||
Esp Async WebServer@1.2.0
|
||||
IRremoteESP8266@2.7.3
|
||||
I2Cdevlib-MPU6050@fbde122cc5
|
||||
```
|
||||
|
||||
## Wiring
|
||||
|
||||
The connections needed to the MPU6050 are as follows:
|
||||
```
|
||||
VCC VU (5V USB) Not available on all boards so use 3.3V if needed.
|
||||
GND G Ground
|
||||
SCL D1 (GPIO05) I2C clock
|
||||
SDA D2 (GPIO04) I2C data
|
||||
XDA not connected
|
||||
XCL not connected
|
||||
AD0 not connected
|
||||
INT D8 (GPIO15) Interrupt pin
|
||||
```
|
||||
|
||||
You could probably modify the code not to need an interrupt, but I used the
|
||||
setup directly from the example.
|
||||
|
||||
## JSON API
|
||||
|
||||
This code adds:
|
||||
```json
|
||||
"u":{
|
||||
"IMU":{
|
||||
"Quat": [w, x, y, z],
|
||||
"Euler": [psi, theta, phi],
|
||||
"Gyro": [x, y, z],
|
||||
"Accel": [x, y, z],
|
||||
"RealAccel": [x, y, z],
|
||||
"WorldAccel": [x, y, z],
|
||||
"Gravity": [x, y, z],
|
||||
"Orientation": [yaw, pitch, roll]
|
||||
}
|
||||
}
|
||||
```
|
||||
to the info object
|
||||
|
||||
## Usermod installation
|
||||
|
||||
1. Copy the file `usermod_mpu6050_imu.h` to the `wled00` directory.
|
||||
2. Register the usermod by adding `#include "usermod_mpu6050_imu.h.h"` in the top and `registerUsermod(new MPU6050Driver());` in the bottom of `usermods_list.cpp`.
|
||||
|
||||
Example **usermods_list.cpp**:
|
||||
|
||||
```cpp
|
||||
#include "wled.h"
|
||||
|
||||
#include "usermod_mpu6050_imu.h"
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
usermods.add(new MPU6050Driver());
|
||||
}
|
||||
```
|
274
usermods/mpu6050_imu/usermod_mpu6050_imu.h
Normal file
@@ -0,0 +1,274 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
/* This driver reads quaternion data from the MPU6060 and adds it to the JSON
|
||||
This example is adapted from:
|
||||
https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi
|
||||
|
||||
Tested with a d1 mini esp-12f
|
||||
|
||||
GY-521 NodeMCU
|
||||
MPU6050 devkit 1.0
|
||||
board Lolin Description
|
||||
======= ========== ====================================================
|
||||
VCC VU (5V USB) Not available on all boards so use 3.3V if needed.
|
||||
GND G Ground
|
||||
SCL D1 (GPIO05) I2C clock
|
||||
SDA D2 (GPIO04) I2C data
|
||||
XDA not connected
|
||||
XCL not connected
|
||||
AD0 not connected
|
||||
INT D8 (GPIO15) Interrupt pin
|
||||
|
||||
Using usermod:
|
||||
1. Copy the usermod into the sketch folder (same folder as wled00.ino)
|
||||
2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||
3. I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h file
|
||||
for both classes must be in the include path of your project. To install the
|
||||
libraries add I2Cdevlib-MPU6050@fbde122cc5 to lib_deps in the platformio.ini file.
|
||||
4. You also need to change lib_compat_mode from strict to soft in platformio.ini (This ignores that I2Cdevlib-MPU6050 doesn't list platform compatibility)
|
||||
5. Wire up the MPU6050 as detailed above.
|
||||
*/
|
||||
|
||||
#include "I2Cdev.h"
|
||||
|
||||
#include "MPU6050_6Axis_MotionApps20.h"
|
||||
//#include "MPU6050.h" // not necessary if using MotionApps include file
|
||||
|
||||
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
|
||||
// is used in I2Cdev.h
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
|
||||
#include "Wire.h"
|
||||
#endif
|
||||
|
||||
// ================================================================
|
||||
// === INTERRUPT DETECTION ROUTINE ===
|
||||
// ================================================================
|
||||
|
||||
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
|
||||
void IRAM_ATTR dmpDataReady() {
|
||||
mpuInterrupt = true;
|
||||
}
|
||||
|
||||
|
||||
class MPU6050Driver : public Usermod {
|
||||
private:
|
||||
MPU6050 mpu;
|
||||
|
||||
// MPU control/status vars
|
||||
bool dmpReady = false; // set true if DMP init was successful
|
||||
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
|
||||
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
|
||||
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
|
||||
uint16_t fifoCount; // count of all bytes currently in FIFO
|
||||
uint8_t fifoBuffer[64]; // FIFO storage buffer
|
||||
|
||||
//NOTE: some of these can be removed to save memory, processing time
|
||||
// if the measurement isn't needed
|
||||
Quaternion qat; // [w, x, y, z] quaternion container
|
||||
float euler[3]; // [psi, theta, phi] Euler angle container
|
||||
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container
|
||||
VectorInt16 aa; // [x, y, z] accel sensor measurements
|
||||
VectorInt16 gy; // [x, y, z] gyro sensor measurements
|
||||
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
|
||||
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
|
||||
VectorFloat gravity; // [x, y, z] gravity vector
|
||||
|
||||
static const int INTERRUPT_PIN = 15; // use pin 15 on ESP8266
|
||||
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
*/
|
||||
void setup() {
|
||||
// join I2C bus (I2Cdev library doesn't do this automatically)
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
|
||||
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
|
||||
Fastwire::setup(400, true);
|
||||
#endif
|
||||
|
||||
// initialize device
|
||||
Serial.println(F("Initializing I2C devices..."));
|
||||
mpu.initialize();
|
||||
pinMode(INTERRUPT_PIN, INPUT);
|
||||
|
||||
// verify connection
|
||||
Serial.println(F("Testing device connections..."));
|
||||
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
|
||||
|
||||
// load and configure the DMP
|
||||
Serial.println(F("Initializing DMP..."));
|
||||
devStatus = mpu.dmpInitialize();
|
||||
|
||||
// supply your own gyro offsets here, scaled for min sensitivity
|
||||
mpu.setXGyroOffset(220);
|
||||
mpu.setYGyroOffset(76);
|
||||
mpu.setZGyroOffset(-85);
|
||||
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
|
||||
|
||||
// make sure it worked (returns 0 if so)
|
||||
if (devStatus == 0) {
|
||||
// turn on the DMP, now that it's ready
|
||||
Serial.println(F("Enabling DMP..."));
|
||||
mpu.setDMPEnabled(true);
|
||||
|
||||
// enable Arduino interrupt detection
|
||||
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
|
||||
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
|
||||
mpuIntStatus = mpu.getIntStatus();
|
||||
|
||||
// set our DMP Ready flag so the main loop() function knows it's okay to use it
|
||||
Serial.println(F("DMP ready! Waiting for first interrupt..."));
|
||||
dmpReady = true;
|
||||
|
||||
// get expected DMP packet size for later comparison
|
||||
packetSize = mpu.dmpGetFIFOPacketSize();
|
||||
} else {
|
||||
// ERROR!
|
||||
// 1 = initial memory load failed
|
||||
// 2 = DMP configuration updates failed
|
||||
// (if it's going to break, usually the code will be 1)
|
||||
Serial.print(F("DMP Initialization failed (code "));
|
||||
Serial.print(devStatus);
|
||||
Serial.println(F(")"));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected() {
|
||||
//Serial.println("Connected to WiFi!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*/
|
||||
void loop() {
|
||||
// if programming failed, don't try to do anything
|
||||
if (!dmpReady) return;
|
||||
|
||||
// wait for MPU interrupt or extra packet(s) available
|
||||
if (!mpuInterrupt && fifoCount < packetSize) return;
|
||||
|
||||
// reset interrupt flag and get INT_STATUS byte
|
||||
mpuInterrupt = false;
|
||||
mpuIntStatus = mpu.getIntStatus();
|
||||
|
||||
// get current FIFO count
|
||||
fifoCount = mpu.getFIFOCount();
|
||||
|
||||
// check for overflow (this should never happen unless our code is too inefficient)
|
||||
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
|
||||
// reset so we can continue cleanly
|
||||
mpu.resetFIFO();
|
||||
Serial.println(F("FIFO overflow!"));
|
||||
|
||||
// otherwise, check for DMP data ready interrupt (this should happen frequently)
|
||||
} else if (mpuIntStatus & 0x02) {
|
||||
// wait for correct available data length, should be a VERY short wait
|
||||
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
|
||||
|
||||
// read a packet from FIFO
|
||||
mpu.getFIFOBytes(fifoBuffer, packetSize);
|
||||
|
||||
// track FIFO count here in case there is > 1 packet available
|
||||
// (this lets us immediately read more without waiting for an interrupt)
|
||||
fifoCount -= packetSize;
|
||||
|
||||
|
||||
//NOTE: some of these can be removed to save memory, processing time
|
||||
// if the measurement isn't needed
|
||||
mpu.dmpGetQuaternion(&qat, fifoBuffer);
|
||||
mpu.dmpGetEuler(euler, &qat);
|
||||
mpu.dmpGetGravity(&gravity, &qat);
|
||||
mpu.dmpGetGyro(&gy, fifoBuffer);
|
||||
mpu.dmpGetAccel(&aa, fifoBuffer);
|
||||
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
|
||||
mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &qat);
|
||||
mpu.dmpGetYawPitchRoll(ypr, &qat, &gravity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray imu_meas = user.createNestedObject("IMU");
|
||||
JsonArray quat_json = imu_meas.createNestedArray("Quat");
|
||||
quat_json.add(qat.w);
|
||||
quat_json.add(qat.x);
|
||||
quat_json.add(qat.y);
|
||||
quat_json.add(qat.z);
|
||||
JsonArray euler_json = imu_meas.createNestedArray("Euler");
|
||||
euler_json.add(euler[0]);
|
||||
euler_json.add(euler[1]);
|
||||
euler_json.add(euler[2]);
|
||||
JsonArray accel_json = imu_meas.createNestedArray("Accel");
|
||||
accel_json.add(aa.x);
|
||||
accel_json.add(aa.y);
|
||||
accel_json.add(aa.z);
|
||||
JsonArray gyro_json = imu_meas.createNestedArray("Gyro");
|
||||
gyro_json.add(gy.x);
|
||||
gyro_json.add(gy.y);
|
||||
gyro_json.add(gy.z);
|
||||
JsonArray world_json = imu_meas.createNestedArray("WorldAccel");
|
||||
world_json.add(aaWorld.x);
|
||||
world_json.add(aaWorld.y);
|
||||
world_json.add(aaWorld.z);
|
||||
JsonArray real_json = imu_meas.createNestedArray("RealAccel");
|
||||
real_json.add(aaReal.x);
|
||||
real_json.add(aaReal.y);
|
||||
real_json.add(aaReal.z);
|
||||
JsonArray grav_json = imu_meas.createNestedArray("Gravity");
|
||||
grav_json.add(gravity.x);
|
||||
grav_json.add(gravity.y);
|
||||
grav_json.add(gravity.z);
|
||||
JsonArray orient_json = imu_meas.createNestedArray("Orientation");
|
||||
orient_json.add(ypr[0]);
|
||||
orient_json.add(ypr[1]);
|
||||
orient_json.add(ypr[2]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
*/
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_IMU;
|
||||
}
|
||||
|
||||
};
|
11
usermods/photoresistor_sensor_mqtt_v1/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Photoresister sensor with MQTT
|
||||
|
||||
This simple usermod allows attaching a photoresistor sensor like the KY-018 and publish the readings in percentage over MQTT. The frequency of MQTT messages can be modified, and there is a threshold value that can be set so that significant changes in the readings can be published immediately instead of waiting for the next update. This was found to be a good compromise between spamming MQTT messages and delayed updates.
|
||||
|
||||
I also found it useful to limit the frequency of analog pin reads because otherwise the board hangs.
|
||||
|
||||
This usermod has only been tested with the KY-018 sensor though should work for any other analog pin sensor. Note that this does not control the LED strip directly, it only publishes MQTT readings for use with other integrations like Home Assistant.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy and replace the file `usermod.cpp` in wled00 directory.
|
70
usermods/photoresistor_sensor_mqtt_v1/usermod.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This v1 usermod file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
|
||||
*
|
||||
* Consider the v2 usermod API if you need a more advanced feature set!
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
const int LIGHT_PIN = A0; // define analog pin
|
||||
const long UPDATE_MS = 30000; // Upper threshold between mqtt messages
|
||||
const char MQTT_TOPIC[] = "/light"; // MQTT topic for sensor values
|
||||
const int CHANGE_THRESHOLD = 5; // Change threshold in percentage to send before UPDATE_MS
|
||||
|
||||
// variables
|
||||
long lastTime = 0;
|
||||
long timeDiff = 0;
|
||||
long readTime = 0;
|
||||
int lightValue = 0;
|
||||
float lightPercentage = 0;
|
||||
float lastPercentage = 0;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
pinMode(LIGHT_PIN, INPUT);
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void publishMqtt(float state)
|
||||
{
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr){
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, MQTT_TOPIC);
|
||||
mqtt->publish(subuf, 0, true, String(state).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
// Read only every 500ms, otherwise it causes the board to hang
|
||||
if (millis() - readTime > 500)
|
||||
{
|
||||
readTime = millis();
|
||||
timeDiff = millis() - lastTime;
|
||||
|
||||
// Convert value to percentage
|
||||
lightValue = analogRead(LIGHT_PIN);
|
||||
lightPercentage = ((float)lightValue * -1 + 1024)/(float)1024 *100;
|
||||
|
||||
// Send MQTT message on significant change or after UPDATE_MS
|
||||
if (abs(lightPercentage - lastPercentage) > CHANGE_THRESHOLD || timeDiff > UPDATE_MS)
|
||||
{
|
||||
publishMqtt(lightPercentage);
|
||||
lastTime = millis();
|
||||
lastPercentage = lightPercentage;
|
||||
}
|
||||
}
|
||||
}
|
23
usermods/project_cars_shiftlight/readme.md
Normal file
@@ -0,0 +1,23 @@
|
||||
### Shift Light for Project Cars
|
||||
|
||||
Turn your WLED lights into a rev light and shift indicator for Project Cars.
|
||||
|
||||
It is pretty straight forward to use.
|
||||
|
||||
1. Make sure, your WLED device and your PC/console are on the same network and can talk to each other
|
||||
|
||||
2. Go to the gameplay settings menu in PCARS and enable UDP. There are 9 numbers you can choose from. This is the refresh rate. The lower the number, the better. But you might run into problems at faster rates.
|
||||
|
||||
| Number | Updates/Second |
|
||||
| ------ | -------------- |
|
||||
| 1 | 60 |
|
||||
| 2 | 50 |
|
||||
| 3 | 40 |
|
||||
| 4 | 30 |
|
||||
| 5 | 20 |
|
||||
| 6 | 15 |
|
||||
| 7 | 10 |
|
||||
| 8 | 05 |
|
||||
| 9 | 1 |
|
||||
|
||||
3. once you enter a race, WLED should automatically shift to PCARS mode. Done.
|
95
usermods/project_cars_shiftlight/wled06_usermod.ino
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Car rev display and shift indicator for Project Cars
|
||||
*
|
||||
* This works via the UDP telemetry function. You'll need to enable it in the settings of the game.
|
||||
* I've had good results with settings around 5 (20 fps).
|
||||
*
|
||||
*/
|
||||
const uint8_t PCARS_dimcolor = 20;
|
||||
WiFiUDP UDP;
|
||||
const unsigned int PCARS_localUdpPort = 5606; // local port to listen on
|
||||
char PCARS_packet[2048];
|
||||
|
||||
char PCARS_tempChar[2]; // Temporary array for u16 conversion
|
||||
|
||||
u16 PCARS_RPM;
|
||||
u16 PCARS_maxRPM;
|
||||
|
||||
long PCARS_lastRead = millis() - 2001;
|
||||
float PCARS_rpmRatio;
|
||||
|
||||
void PCARS_readValues() {
|
||||
|
||||
int PCARS_packetSize = UDP.parsePacket();
|
||||
if (PCARS_packetSize) {
|
||||
int len = UDP.read(PCARS_packet, PCARS_packetSize);
|
||||
if (len > 0) {
|
||||
PCARS_packet[len] = 0;
|
||||
}
|
||||
if (len == 1367) { // Telemetry packet. Ignoring everything else.
|
||||
PCARS_lastRead = millis();
|
||||
|
||||
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_GENERIC);
|
||||
// current RPM
|
||||
memcpy(&PCARS_tempChar, &PCARS_packet[124], 2);
|
||||
PCARS_RPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
|
||||
|
||||
// max RPM
|
||||
memcpy(&PCARS_tempChar, &PCARS_packet[126], 2);
|
||||
PCARS_maxRPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
|
||||
|
||||
if (PCARS_maxRPM) {
|
||||
PCARS_rpmRatio = constrain((float)PCARS_RPM / (float)PCARS_maxRPM, 0, 1);
|
||||
} else {
|
||||
PCARS_rpmRatio = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void PCARS_buildcolorbars() {
|
||||
boolean activated = false;
|
||||
float ledratio = 0;
|
||||
|
||||
for (uint16_t i = 0; i < ledCount; i++) {
|
||||
if (PCARS_rpmRatio < .95 || (millis() % 100 > 70 )) {
|
||||
|
||||
ledratio = (float)i / (float)ledCount;
|
||||
if (ledratio < PCARS_rpmRatio) {
|
||||
activated = true;
|
||||
} else {
|
||||
activated = false;
|
||||
}
|
||||
if (ledratio > 0.66) {
|
||||
setRealtimePixel(i, 0, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0);
|
||||
} else if (ledratio > 0.33) {
|
||||
setRealtimePixel(i, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0, 0);
|
||||
} else {
|
||||
setRealtimePixel(i, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
setRealtimePixel(i, 0, 0, 0, 0);
|
||||
|
||||
}
|
||||
}
|
||||
colorUpdated(5);
|
||||
strip.show();
|
||||
}
|
||||
|
||||
void userSetup()
|
||||
{
|
||||
UDP.begin(PCARS_localUdpPort);
|
||||
}
|
||||
|
||||
void userConnected()
|
||||
{
|
||||
// new wifi, who dis?
|
||||
}
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
PCARS_readValues();
|
||||
if (PCARS_lastRead > millis() - 2000) {
|
||||
PCARS_buildcolorbars();
|
||||
}
|
||||
}
|
21
usermods/readme.md
Normal file
@@ -0,0 +1,21 @@
|
||||
### Usermods
|
||||
|
||||
This folder serves as a repository for usermods (custom `usermod.cpp` files)!
|
||||
|
||||
If you have created an usermod that you believe is useful (for example to support a particular sensor, display, feature...), feel free to contribute by opening a pull request!
|
||||
|
||||
In order for other people to be able to have fun with your usermod, please keep these points in mind:
|
||||
|
||||
- Create a folder in this folder with a descriptive name (for example `usermod_ds18b20_temp_sensor_mqtt`)
|
||||
- Include your custom files
|
||||
- If your usermod requires changes to other WLED files, please write a `readme.md` outlining the steps one has to take to use the usermod
|
||||
- Create a pull request!
|
||||
- If your feature is useful for the majority of WLED users, I will consider adding it to the base code!
|
||||
|
||||
While I do my best to not break too much, keep in mind that as WLED is being updated, usermods might break.
|
||||
I am not actively maintaining any usermod in this directory, that is your responsibility as the creator of the usermod.
|
||||
|
||||
For new usermods, I would recommend trying out the new v2 usermod API, which allows installing multiple usermods at once and new functions!
|
||||
You can take a look at `EXAMPLE_v2` for some documentation and at `Temperature` for a completed v2 usermod!
|
||||
|
||||
Thank you for your help :)
|
62
usermods/rotary_encoder_change_brightness/usermod.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
/*
|
||||
** Rotary Encoder Example
|
||||
** Use the Sparkfun Rotary Encoder to vary brightness of LED
|
||||
**
|
||||
** Sample the encoder at 500Hz using the millis() function
|
||||
*/
|
||||
|
||||
int fadeAmount = 5; // how many points to fade the Neopixel with each step
|
||||
unsigned long currentTime;
|
||||
unsigned long loopTime;
|
||||
const int pinA = D6; // DT from encoder
|
||||
const int pinB = D7; // CLK from encoder
|
||||
|
||||
unsigned char Enc_A;
|
||||
unsigned char Enc_B;
|
||||
unsigned char Enc_A_prev = 0;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
pinMode(pinA, INPUT_PULLUP);
|
||||
pinMode(pinB, INPUT_PULLUP);
|
||||
currentTime = millis();
|
||||
loopTime = currentTime;
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected() {
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop() {
|
||||
currentTime = millis(); // get the current elapsed time
|
||||
if(currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
||||
{
|
||||
int Enc_A = digitalRead(pinA); // Read encoder pins
|
||||
int Enc_B = digitalRead(pinB);
|
||||
if((! Enc_A) && (Enc_A_prev)) { // A has gone from high to low
|
||||
if(Enc_B == HIGH) { // B is high so clockwise
|
||||
if(bri + fadeAmount <= 255) bri += fadeAmount; // increase the brightness, dont go over 255
|
||||
|
||||
} else if (Enc_B == LOW) { // B is low so counter-clockwise
|
||||
if(bri - fadeAmount >= 0) bri -= fadeAmount; // decrease the brightness, dont go below 0
|
||||
}
|
||||
}
|
||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(6);
|
||||
}
|
||||
}
|
211
usermods/rotary_encoder_change_brightness/usermode_rotary_set.h
Normal file
@@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
//v2 usermod that allows to change brightness and color using a rotary encoder,
|
||||
//change between modes by pressing a button (many encoder have one included)
|
||||
class RotaryEncoderSet : public Usermod
|
||||
{
|
||||
private:
|
||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
unsigned long lastTime = 0;
|
||||
/*
|
||||
** Rotary Encoder Example
|
||||
** Use the Sparkfun Rotary Encoder to vary brightness of LED
|
||||
**
|
||||
** Sample the encoder at 500Hz using the millis() function
|
||||
*/
|
||||
|
||||
int fadeAmount = 5; // how many points to fade the Neopixel with each step
|
||||
unsigned long currentTime;
|
||||
unsigned long loopTime;
|
||||
const int pinA = 5; // DT from encoder
|
||||
const int pinB = 18; // CLK from encoder
|
||||
const int pinC = 23; // SW from encoder
|
||||
unsigned char select_state = 0; // 0 = brightness 1 = color
|
||||
unsigned char button_state = HIGH;
|
||||
unsigned char prev_button_state = HIGH;
|
||||
CRGB fastled_col;
|
||||
CHSV prim_hsv;
|
||||
int16_t new_val;
|
||||
|
||||
unsigned char Enc_A;
|
||||
unsigned char Enc_B;
|
||||
unsigned char Enc_A_prev = 0;
|
||||
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
//Serial.println("Hello from my usermod!");
|
||||
pinMode(pinA, INPUT_PULLUP);
|
||||
pinMode(pinB, INPUT_PULLUP);
|
||||
pinMode(pinC, INPUT_PULLUP);
|
||||
currentTime = millis();
|
||||
loopTime = currentTime;
|
||||
}
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected()
|
||||
{
|
||||
//Serial.println("Connected to WiFi!");
|
||||
}
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
currentTime = millis(); // get the current elapsed time
|
||||
|
||||
if (currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
||||
{
|
||||
button_state = digitalRead(pinC);
|
||||
if (prev_button_state != button_state)
|
||||
{
|
||||
if (button_state == LOW)
|
||||
{
|
||||
if (select_state == 1)
|
||||
{
|
||||
select_state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
select_state = 1;
|
||||
}
|
||||
prev_button_state = button_state;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_button_state = button_state;
|
||||
}
|
||||
}
|
||||
int Enc_A = digitalRead(pinA); // Read encoder pins
|
||||
int Enc_B = digitalRead(pinB);
|
||||
if ((!Enc_A) && (Enc_A_prev))
|
||||
{ // A has gone from high to low
|
||||
if (Enc_B == HIGH)
|
||||
{ // B is high so clockwise
|
||||
if (select_state == 0)
|
||||
{
|
||||
if (bri + fadeAmount <= 255)
|
||||
bri += fadeAmount; // increase the brightness, dont go over 255
|
||||
}
|
||||
else
|
||||
{
|
||||
fastled_col.red = col[0];
|
||||
fastled_col.green = col[1];
|
||||
fastled_col.blue = col[2];
|
||||
prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||
new_val = (int16_t)prim_hsv.h + fadeAmount;
|
||||
if (new_val > 255)
|
||||
new_val -= 255; // roll-over if bigger than 255
|
||||
if (new_val < 0)
|
||||
new_val += 255; // roll-over if smaller than 0
|
||||
prim_hsv.h = (byte)new_val;
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
col[0] = fastled_col.red;
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
}
|
||||
else if (Enc_B == LOW)
|
||||
{ // B is low so counter-clockwise
|
||||
if (select_state == 0)
|
||||
{
|
||||
if (bri - fadeAmount >= 0)
|
||||
bri -= fadeAmount; // decrease the brightness, dont go below 0
|
||||
}
|
||||
else
|
||||
{
|
||||
fastled_col.red = col[0];
|
||||
fastled_col.green = col[1];
|
||||
fastled_col.blue = col[2];
|
||||
prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||
new_val = (int16_t)prim_hsv.h - fadeAmount;
|
||||
if (new_val > 255)
|
||||
new_val -= 255; // roll-over if bigger than 255
|
||||
if (new_val < 0)
|
||||
new_val += 255; // roll-over if smaller than 0
|
||||
prim_hsv.h = (byte)new_val;
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
col[0] = fastled_col.red;
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
}
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
updateInterfaces()
|
||||
}
|
||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
/*
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void addToJsonState(JsonObject &root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void readFromJsonState(JsonObject &root)
|
||||
{
|
||||
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
*/
|
||||
uint16_t getId()
|
||||
{
|
||||
return 0xABCD;
|
||||
}
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
45
usermods/rotary_encoder_change_effect/wled06_usermod.ino
Normal file
@@ -0,0 +1,45 @@
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
long lastTime = 0;
|
||||
int delayMs = 10;
|
||||
const int pinA = D6; //data
|
||||
const int pinB = D7; //clk
|
||||
int oldA = LOW;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
pinMode(pinA, INPUT_PULLUP);
|
||||
pinMode(pinB, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected() {
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop() {
|
||||
if (millis()-lastTime > delayMs) {
|
||||
int A = digitalRead(pinA);
|
||||
int B = digitalRead(pinB);
|
||||
|
||||
if (oldA == LOW && A == HIGH) {
|
||||
if (oldB == HIGH) {
|
||||
// bri += 10;
|
||||
// if (bri > 250) bri = 10;
|
||||
effectCurrent += 1;
|
||||
if (effectCurrent >= MODE_COUNT) effectCurrent = 0;
|
||||
}
|
||||
else {
|
||||
// bri -= 10;
|
||||
// if (bri < 10) bri = 250;
|
||||
effectCurrent -= 1;
|
||||
if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1);
|
||||
}
|
||||
oldA = A;
|
||||
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
35
usermods/ssd1306_i2c_oled_u8g2/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# SSD1306 128x32 OLED via I2C with u8g2
|
||||
This usermod allows to connect 128x32 Oled display to WLED controlled and show
|
||||
the next information:
|
||||
- Current SSID
|
||||
- IP address if obtained
|
||||
* in AP mode and turned off lightning AP password is shown
|
||||
- Current effect
|
||||
- Current palette
|
||||
- On/Off icon (sun/moon)
|
||||
|
||||
## Hardware
|
||||

|
||||
|
||||
## Requirements
|
||||
Functionality checked with:
|
||||
- commit 095429a7df4f9e2b34dd464f7bbfd068df6558eb
|
||||
- Wemos d1 mini
|
||||
- PlatformIO
|
||||
- Generic SSD1306 128x32 I2C OLED display from aliexpress
|
||||
|
||||
### Platformio
|
||||
Add `U8g2@~2.27.2` dependency to `lib_deps_external` under `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
U8g2@~2.27.2
|
||||
...
|
||||
```
|
||||
|
||||
### Arduino IDE
|
||||
Install library `U8g2 by oliver` in `Tools | Include Library | Manage libraries` menu.
|
BIN
usermods/ssd1306_i2c_oled_u8g2/assets/hw_connection.png
Normal file
After Width: | Height: | Size: 34 KiB |
175
usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino
Normal file
@@ -0,0 +1,175 @@
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//Lolin32 boards use SCL=5 SDA=4
|
||||
#define U8X8_PIN_SCL 5
|
||||
#define U8X8_PIN_SDA 4
|
||||
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL,
|
||||
U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
|
||||
// gets called once at boot. Do all initialization that doesn't depend on
|
||||
// network here
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
14
usermods/stairway_wipe_basic/readme.md
Normal file
@@ -0,0 +1,14 @@
|
||||
### Stairway lighting
|
||||
|
||||
Quick usermod to accomplish something similar to [this video](https://www.youtube.com/watch?v=NHkju5ncC4A).
|
||||
|
||||
This usermod allows you to add a lightstrip alongside or on the steps of a staircase.
|
||||
When the `userVar0` variable is set, the LEDs will gradually turn on in a Wipe effect.
|
||||
Both directions are supported by setting userVar0 to 1 and 2, respectively (HTTP API commands `U0=1` and `U0=2`).
|
||||
|
||||
After the Wipe is complete, the light will either stay on (Solid effect) indefinitely or after `userVar1` seconds have elapsed.
|
||||
If userVar0 is updated (e.g. by triggering a second sensor) the light will slowly fade off.
|
||||
This could be extended to also run a Wipe effect in reverse order to turn the LEDs back off.
|
||||
|
||||
This is just a basic version to accomplish this using HTTP API calls `U0` and `U1` and/or macros.
|
||||
It should be easy to adapt this code however to interface with motion sensors or other input devices.
|
111
usermods/stairway_wipe_basic/wled06_usermod.ino
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
byte wipeState = 0; //0: inactive 1: wiping 2: solid
|
||||
unsigned long timeStaticStart = 0;
|
||||
uint16_t previousUserVar0 = 0;
|
||||
|
||||
//comment this out if you want the turn off effect to be just fading out instead of reverse wipe
|
||||
#define STAIRCASE_WIPE_OFF
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
//setup PIR sensor here, if needed
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
//userVar0 (U0 in HTTP API):
|
||||
//has to be set to 1 if movement is detected on the PIR that is the same side of the staircase as the ESP8266
|
||||
//has to be set to 2 if movement is detected on the PIR that is the opposite side
|
||||
//can be set to 0 if no movement is detected. Otherwise LEDs will turn off after a configurable timeout (userVar1 seconds)
|
||||
|
||||
if (userVar0 > 0)
|
||||
{
|
||||
if ((previousUserVar0 == 1 && userVar0 == 2) || (previousUserVar0 == 2 && userVar0 == 1)) wipeState = 3; //turn off if other PIR triggered
|
||||
previousUserVar0 = userVar0;
|
||||
|
||||
if (wipeState == 0) {
|
||||
startWipe();
|
||||
wipeState = 1;
|
||||
} else if (wipeState == 1) { //wiping
|
||||
uint32_t cycleTime = 360 + (255 - effectSpeed)*75; //this is how long one wipe takes (minus 25 ms to make sure we switch in time)
|
||||
if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete
|
||||
effectCurrent = FX_MODE_STATIC;
|
||||
timeStaticStart = millis();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 2;
|
||||
}
|
||||
} else if (wipeState == 2) { //static
|
||||
if (userVar1 > 0) //if U1 is not set, the light will stay on until second PIR or external command is triggered
|
||||
{
|
||||
if (millis() - timeStaticStart > userVar1*1000) wipeState = 3;
|
||||
}
|
||||
} else if (wipeState == 3) { //switch to wipe off
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
effectCurrent = FX_MODE_COLOR_WIPE;
|
||||
strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 4;
|
||||
#else
|
||||
turnOff();
|
||||
#endif
|
||||
} else { //wiping off
|
||||
if (millis() + strip.timebase > (725 + (255 - effectSpeed)*150)) turnOff(); //wipe complete
|
||||
}
|
||||
} else {
|
||||
wipeState = 0; //reset for next time
|
||||
if (previousUserVar0) {
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
userVar0 = previousUserVar0;
|
||||
wipeState = 3;
|
||||
#else
|
||||
turnOff();
|
||||
#endif
|
||||
}
|
||||
previousUserVar0 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void startWipe()
|
||||
{
|
||||
bri = briLast; //turn on
|
||||
transitionDelayTemp = 0; //no transition
|
||||
effectCurrent = FX_MODE_COLOR_WIPE;
|
||||
resetTimebase(); //make sure wipe starts from beginning
|
||||
|
||||
//set wipe direction
|
||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
||||
bool doReverse = (userVar0 == 2);
|
||||
seg.setOption(1, doReverse);
|
||||
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
}
|
||||
|
||||
void turnOff()
|
||||
{
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
transitionDelayTemp = 0; //turn off immediately after wipe completed
|
||||
#else
|
||||
transitionDelayTemp = 4000; //fade out slowly
|
||||
#endif
|
||||
bri = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 0;
|
||||
userVar0 = 0;
|
||||
previousUserVar0 = 0;
|
||||
}
|
BIN
usermods/word-clock-matrix/Word Clock Baffle.stl
Normal file
6
usermods/word-clock-matrix/readme.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## Word clock usermod
|
||||
|
||||
By @bwente
|
||||
|
||||
See https://www.hackster.io/bwente/word-clock-with-just-two-components-073834 for the hardware guide!
|
||||
Includes a customizable feature to lower the brightness at night.
|
846
usermods/word-clock-matrix/word clock stencil.svg
Normal file
@@ -0,0 +1,846 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="288px" height="288px" viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#E82429;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#E82429;stroke-width:0.9999;stroke-miterlimit:10;}
|
||||
.st2{fill:#231F20;}
|
||||
.st3{fill:none;stroke:#231F20;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="55.888" y="99.803" class="st0" width="41.1" height="19"/>
|
||||
<polygon class="st0" points="101.188,142.003 119.688,142.003 119.688,123.003 101.188,123.003 96.988,123.003 55.888,123.003
|
||||
55.888,142.003 96.988,142.003 "/>
|
||||
<rect x="123.888" y="146.303" class="st0" width="41.1" height="19"/>
|
||||
<rect x="55.888" y="192.803" class="st0" width="41.1" height="19"/>
|
||||
<rect x="123.888" y="169.503" class="st0" width="41.1" height="19"/>
|
||||
<polygon class="st0" points="169.288,118.803 187.688,118.803 187.688,99.803 146.588,99.803 142.288,99.803 101.188,99.803
|
||||
101.188,118.803 119.688,118.803 123.888,118.803 164.988,118.803 "/>
|
||||
<polygon class="st0" points="74.388,146.303 55.888,146.303 55.888,165.303 119.688,165.303 119.688,146.303 78.588,146.303 "/>
|
||||
<rect x="123.888" y="123.003" class="st0" width="41.1" height="19"/>
|
||||
<polygon class="st0" points="101.188,95.603 142.288,95.603 142.288,76.603 101.188,76.603 96.988,76.603 55.888,76.603
|
||||
55.888,95.603 96.988,95.603 "/>
|
||||
<polygon class="st0" points="96.988,216.003 55.888,216.003 55.888,235.003 142.288,235.003 142.288,216.003 101.188,216.003
|
||||
"/>
|
||||
<rect x="55.888" y="53.303" class="st0" width="41.1" height="19"/>
|
||||
<polygon class="st0" points="187.688,76.603 146.588,76.603 146.588,95.603 187.688,95.603 191.888,95.603 232.988,95.603
|
||||
232.988,76.603 191.888,76.603 "/>
|
||||
<rect x="191.988" y="192.803" class="st0" width="41.1" height="19"/>
|
||||
<polygon class="st0" points="146.588,72.303 187.688,72.303 187.688,53.303 101.188,53.303 101.188,72.303 142.288,72.303 "/>
|
||||
<rect x="191.888" y="99.803" class="st0" width="41.1" height="19"/>
|
||||
<rect x="191.888" y="53.303" class="st0" width="41.1" height="19"/>
|
||||
<polygon class="st0" points="187.688,123.003 169.288,123.003 169.288,142.003 232.988,142.003 232.988,123.003 191.888,123.003
|
||||
"/>
|
||||
<rect x="146.588" y="216.003" class="st0" width="86.5" height="19"/>
|
||||
<polygon class="st0" points="119.688,188.503 119.688,169.503 55.888,169.503 55.888,188.503 96.988,188.503 101.288,188.503
|
||||
"/>
|
||||
<rect x="169.288" y="146.303" class="st0" width="63.8" height="19"/>
|
||||
<polygon class="st0" points="119.588,192.803 101.188,192.803 101.188,211.803 187.588,211.803 187.588,192.803 123.888,192.803
|
||||
"/>
|
||||
<rect x="169.288" y="169.503" class="st0" width="63.8" height="19"/>
|
||||
</g>
|
||||
<rect x="31.102" y="30.767" class="st1" width="226.772" height="226.772"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M62.154,59.463c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V59.463z"/>
|
||||
<path class="st2" d="M67.014,58.395h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C66.546,58.431,66.75,58.395,67.014,58.395z"/>
|
||||
<path class="st2" d="M80.646,59.463c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V59.463z"/>
|
||||
<path class="st2" d="M85.061,65.967c-0.208-0.256-0.312-0.485-0.312-0.689s0.172-0.475,0.516-0.811
|
||||
c0.2-0.191,0.412-0.288,0.636-0.288c0.224,0,0.536,0.2,0.936,0.601c0.112,0.136,0.271,0.266,0.48,0.39
|
||||
c0.208,0.124,0.4,0.187,0.576,0.187c0.744,0,1.116-0.305,1.116-0.912c0-0.185-0.102-0.338-0.306-0.462
|
||||
c-0.204-0.124-0.458-0.214-0.762-0.271c-0.304-0.056-0.632-0.146-0.984-0.27s-0.68-0.271-0.984-0.438s-0.558-0.434-0.762-0.798
|
||||
c-0.204-0.364-0.306-0.802-0.306-1.313c0-0.704,0.262-1.318,0.786-1.843c0.524-0.523,1.238-0.786,2.142-0.786
|
||||
c0.48,0,0.918,0.062,1.314,0.187c0.396,0.124,0.67,0.25,0.822,0.378l0.3,0.228c0.248,0.232,0.372,0.429,0.372,0.589
|
||||
s-0.096,0.38-0.288,0.659c-0.272,0.4-0.552,0.601-0.84,0.601c-0.168,0-0.376-0.08-0.624-0.24c-0.024-0.016-0.07-0.056-0.138-0.12
|
||||
c-0.068-0.063-0.13-0.115-0.186-0.156c-0.168-0.104-0.382-0.155-0.642-0.155c-0.26,0-0.476,0.062-0.648,0.186
|
||||
c-0.172,0.124-0.258,0.296-0.258,0.517c0,0.22,0.102,0.397,0.306,0.533c0.204,0.137,0.458,0.229,0.762,0.276
|
||||
c0.304,0.048,0.636,0.122,0.996,0.222c0.36,0.101,0.692,0.223,0.996,0.366c0.304,0.145,0.558,0.395,0.762,0.75
|
||||
c0.204,0.356,0.306,0.794,0.306,1.314c0,0.52-0.104,0.978-0.312,1.374c-0.208,0.396-0.48,0.701-0.816,0.918
|
||||
c-0.648,0.424-1.34,0.636-2.076,0.636c-0.376,0-0.732-0.046-1.068-0.138c-0.336-0.093-0.608-0.206-0.816-0.343
|
||||
c-0.424-0.256-0.72-0.504-0.888-0.743L85.061,65.967z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M132.579,58.659c0.064-0.12,0.172-0.204,0.324-0.252c0.152-0.049,0.344-0.072,0.576-0.072
|
||||
s0.416,0.02,0.552,0.06c0.136,0.04,0.24,0.089,0.312,0.145c0.072,0.056,0.128,0.136,0.168,0.24c0.04,0.136,0.06,0.344,0.06,0.624
|
||||
v6.659c0,0.185-0.006,0.322-0.018,0.414c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.148-0.984-0.444c-0.048-0.136-0.072-0.344-0.072-0.624v-2.436h-3.18v2.447c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v2.447h3.18v-2.46
|
||||
c0-0.184,0.006-0.321,0.018-0.414C132.477,58.885,132.515,58.779,132.579,58.659z"/>
|
||||
<path class="st2" d="M141.807,58.959l3.24,6.696c0.136,0.271,0.204,0.476,0.204,0.611c0,0.288-0.232,0.548-0.696,0.78
|
||||
c-0.272,0.136-0.486,0.204-0.642,0.204c-0.156,0-0.284-0.036-0.384-0.108c-0.1-0.071-0.172-0.147-0.216-0.228
|
||||
s-0.106-0.2-0.186-0.36l-0.624-1.296h-3.324l-0.624,1.296c-0.08,0.16-0.142,0.276-0.186,0.349
|
||||
c-0.044,0.071-0.116,0.146-0.216,0.222s-0.228,0.114-0.384,0.114c-0.156,0-0.37-0.068-0.642-0.204
|
||||
c-0.464-0.225-0.696-0.48-0.696-0.769c0-0.136,0.068-0.34,0.204-0.611l3.24-6.708c0.088-0.185,0.222-0.332,0.402-0.444
|
||||
c0.18-0.112,0.37-0.168,0.57-0.168C141.279,58.335,141.598,58.543,141.807,58.959z M140.835,61.839l-0.792,1.644h1.596
|
||||
L140.835,61.839z"/>
|
||||
<path class="st2" d="M149.235,65.354h3.264c0.264,0,0.456,0.03,0.576,0.091c0.12,0.06,0.2,0.153,0.24,0.281s0.06,0.299,0.06,0.511
|
||||
s-0.02,0.382-0.06,0.51s-0.108,0.216-0.204,0.264c-0.152,0.08-0.36,0.12-0.624,0.12h-4.32c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624V65.354z"/>
|
||||
<path class="st2" d="M161.175,58.335c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.196,0.051,0.312,0.114
|
||||
c0.116,0.064,0.198,0.172,0.246,0.324s0.072,0.355,0.072,0.612c0,0.256-0.024,0.46-0.072,0.611
|
||||
c-0.048,0.152-0.132,0.258-0.252,0.318c-0.12,0.06-0.226,0.096-0.318,0.107c-0.092,0.013-0.234,0.019-0.426,0.019h-3.672v1.212
|
||||
h2.364c0.192,0,0.334,0.006,0.426,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.208,0.12,0.312,0.437,0.312,0.948
|
||||
c0,0.56-0.152,0.892-0.456,0.996c-0.128,0.04-0.332,0.06-0.612,0.06h-2.352v2.269c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834c0.152-0.147,0.44-0.222,0.864-0.222H161.175z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M200.185,58.389h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C199.716,58.424,199.921,58.389,200.185,58.389z"/>
|
||||
<path class="st2" d="M211.704,65.073h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V65.073z"/>
|
||||
<path class="st2" d="M224.118,58.767c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056C224.004,59.128,224.042,58.907,224.118,58.767z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M75.291,88.03c0.368,0.248,0.632,0.428,0.792,0.54c0.288,0.216,0.432,0.422,0.432,0.617
|
||||
c0,0.196-0.12,0.471-0.36,0.822c-0.24,0.353-0.484,0.528-0.732,0.528c-0.152,0-0.384-0.108-0.696-0.324
|
||||
c-0.041-0.023-0.152-0.1-0.336-0.228s-0.328-0.225-0.432-0.288c-0.744,0.576-1.58,0.863-2.508,0.863
|
||||
c-1.24,0-2.286-0.439-3.138-1.319s-1.278-1.928-1.278-3.145c0-0.664,0.12-1.285,0.36-1.865c0.24-0.58,0.56-1.066,0.96-1.458
|
||||
c0.4-0.393,0.86-0.7,1.38-0.925c0.52-0.224,1.056-0.336,1.608-0.336c1.184,0,2.212,0.429,3.084,1.284
|
||||
c0.872,0.856,1.308,1.94,1.308,3.252C75.735,86.713,75.587,87.373,75.291,88.03z M69.159,86.038c0,0.712,0.23,1.29,0.69,1.733
|
||||
c0.46,0.444,0.974,0.666,1.542,0.666c0.568,0,1.08-0.216,1.536-0.647s0.684-1.012,0.684-1.74c0-0.728-0.23-1.312-0.69-1.752
|
||||
c-0.46-0.439-0.974-0.66-1.542-0.66c-0.568,0-1.08,0.223-1.536,0.666C69.387,84.747,69.159,85.326,69.159,86.038z"/>
|
||||
<path class="st2" d="M83.643,81.946c0.08-0.128,0.196-0.217,0.348-0.265c0.152-0.048,0.342-0.071,0.57-0.071s0.41,0.02,0.546,0.06
|
||||
s0.24,0.088,0.312,0.145c0.072,0.056,0.124,0.14,0.156,0.252c0.048,0.136,0.072,0.344,0.072,0.624v3.624
|
||||
c0,1.056-0.328,2.016-0.984,2.88c-0.32,0.407-0.732,0.737-1.236,0.989c-0.504,0.252-1.062,0.378-1.674,0.378
|
||||
c-0.612,0-1.168-0.128-1.668-0.384s-0.906-0.592-1.218-1.008c-0.648-0.848-0.972-1.808-0.972-2.88v-3.612
|
||||
c0-0.191,0.006-0.334,0.018-0.426c0.012-0.092,0.05-0.198,0.114-0.318c0.064-0.119,0.172-0.204,0.324-0.252
|
||||
s0.356-0.071,0.612-0.071s0.46,0.023,0.612,0.071c0.152,0.048,0.256,0.133,0.312,0.252c0.096,0.185,0.144,0.437,0.144,0.757v3.6
|
||||
c0,0.488,0.12,0.952,0.36,1.392c0.12,0.225,0.3,0.404,0.54,0.54c0.24,0.137,0.524,0.204,0.852,0.204
|
||||
c0.583,0,1.02-0.216,1.308-0.647c0.288-0.433,0.432-0.933,0.432-1.5v-3.672C83.522,82.293,83.563,82.074,83.643,81.946z"/>
|
||||
<path class="st2" d="M92.283,82.246l3.24,6.696c0.136,0.271,0.204,0.476,0.204,0.611c0,0.288-0.232,0.548-0.696,0.78
|
||||
c-0.272,0.136-0.486,0.204-0.642,0.204c-0.156,0-0.284-0.036-0.384-0.108c-0.1-0.071-0.172-0.147-0.216-0.228
|
||||
s-0.106-0.2-0.186-0.36l-0.624-1.296h-3.324l-0.624,1.296c-0.08,0.16-0.142,0.276-0.186,0.349
|
||||
c-0.044,0.071-0.116,0.146-0.216,0.222s-0.228,0.114-0.384,0.114c-0.156,0-0.37-0.068-0.642-0.204
|
||||
c-0.464-0.225-0.696-0.48-0.696-0.769c0-0.136,0.068-0.34,0.204-0.611l3.24-6.708c0.088-0.185,0.222-0.332,0.402-0.444
|
||||
c0.18-0.112,0.37-0.168,0.57-0.168C91.755,81.621,92.075,81.829,92.283,82.246z M91.311,85.125l-0.792,1.644h1.596L91.311,85.125z"
|
||||
/>
|
||||
<path class="st2" d="M104.319,88.929c0.12,0.288,0.18,0.496,0.18,0.624c0,0.305-0.248,0.561-0.744,0.769
|
||||
c-0.256,0.111-0.462,0.168-0.618,0.168c-0.156,0-0.284-0.038-0.384-0.114s-0.174-0.154-0.222-0.234
|
||||
c-0.08-0.151-0.392-0.876-0.936-2.172l-0.372,0.024h-1.512v1.355c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324h2.592c0.704,0,1.388,0.256,2.052,0.768c0.32,0.248,0.584,0.584,0.792,1.009
|
||||
c0.208,0.424,0.312,0.896,0.312,1.416c0,0.903-0.3,1.647-0.9,2.231C103.679,87.469,103.951,88.097,104.319,88.929z M99.711,85.87
|
||||
h1.536c0.232,0,0.464-0.088,0.696-0.264c0.232-0.177,0.348-0.44,0.348-0.792c0-0.353-0.116-0.618-0.348-0.799
|
||||
c-0.232-0.18-0.472-0.27-0.72-0.27h-1.512V85.87z"/>
|
||||
<path class="st2" d="M106.455,81.61h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C105.987,81.645,106.191,81.61,106.455,81.61z"/>
|
||||
<path class="st2" d="M117.975,88.293h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V88.293z"/>
|
||||
<path class="st2" d="M131.438,88.929c0.12,0.288,0.18,0.496,0.18,0.624c0,0.305-0.248,0.561-0.744,0.769
|
||||
c-0.256,0.111-0.462,0.168-0.618,0.168c-0.156,0-0.284-0.038-0.384-0.114s-0.174-0.154-0.222-0.234
|
||||
c-0.08-0.151-0.392-0.876-0.936-2.172l-0.372,0.024h-1.512v1.355c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324h2.592c0.704,0,1.388,0.256,2.052,0.768c0.32,0.248,0.584,0.584,0.792,1.009
|
||||
c0.208,0.424,0.312,0.896,0.312,1.416c0,0.903-0.3,1.647-0.9,2.231C130.798,87.469,131.07,88.097,131.438,88.929z M126.831,85.87
|
||||
h1.536c0.232,0,0.464-0.088,0.696-0.264c0.232-0.177,0.348-0.44,0.348-0.792c0-0.353-0.116-0.618-0.348-0.799
|
||||
c-0.232-0.18-0.472-0.27-0.72-0.27h-1.512V85.87z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M161.062,81.681h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414V83.42h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C160.594,81.716,160.798,81.681,161.062,81.681z"/>
|
||||
<path class="st2" d="M180.981,81.741c0.536,0.192,0.804,0.448,0.804,0.768c0,0.104-0.048,0.301-0.144,0.589l-2.304,6.659
|
||||
c-0.016,0.057-0.044,0.125-0.084,0.204c-0.04,0.08-0.146,0.187-0.318,0.318c-0.172,0.132-0.376,0.198-0.612,0.198
|
||||
c-0.236,0-0.44-0.066-0.612-0.198s-0.286-0.262-0.342-0.39l-1.404-4.141c-0.888,2.624-1.34,3.96-1.356,4.008
|
||||
c-0.016,0.049-0.052,0.116-0.108,0.204c-0.056,0.089-0.12,0.168-0.192,0.24c-0.184,0.185-0.404,0.276-0.66,0.276
|
||||
s-0.466-0.061-0.63-0.181c-0.164-0.119-0.274-0.239-0.33-0.359l-0.084-0.181l-2.316-6.659c-0.088-0.265-0.132-0.46-0.132-0.589
|
||||
c0-0.319,0.268-0.571,0.804-0.756c0.232-0.079,0.442-0.12,0.63-0.12s0.332,0.064,0.432,0.192s0.19,0.324,0.27,0.588l1.32,4.008
|
||||
l1.308-3.947c0.112-0.336,0.316-0.568,0.612-0.696c0.128-0.056,0.294-0.084,0.498-0.084c0.204,0,0.394,0.065,0.57,0.198
|
||||
c0.176,0.132,0.288,0.262,0.336,0.39l1.38,4.164l1.32-4.032c0.064-0.184,0.116-0.319,0.156-0.408
|
||||
c0.04-0.088,0.114-0.174,0.222-0.258s0.242-0.126,0.402-0.126S180.766,81.661,180.981,81.741z"/>
|
||||
<path class="st2" d="M185.769,88.365h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V88.365z"/>
|
||||
<path class="st2" d="M198.184,82.059c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056C198.069,82.42,198.107,82.199,198.184,82.059z"
|
||||
/>
|
||||
<path class="st2" d="M202.917,81.681h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414V83.42h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C202.449,81.716,202.653,81.681,202.917,81.681z"/>
|
||||
<path class="st2" d="M219.297,81.861c0.392,0.272,0.588,0.536,0.588,0.792c0,0.152-0.092,0.364-0.276,0.636l-2.592,3.876v2.292
|
||||
c0,0.185-0.006,0.322-0.018,0.414s-0.05,0.198-0.114,0.318s-0.172,0.204-0.324,0.252s-0.356,0.072-0.612,0.072
|
||||
c-0.256,0-0.46-0.024-0.612-0.072s-0.26-0.134-0.324-0.258c-0.064-0.124-0.102-0.232-0.114-0.324
|
||||
c-0.012-0.092-0.018-0.234-0.018-0.426v-2.269l-2.592-3.876c-0.184-0.271-0.276-0.483-0.276-0.636c0-0.256,0.176-0.502,0.528-0.738
|
||||
c0.352-0.235,0.604-0.354,0.756-0.354s0.272,0.032,0.36,0.096c0.136,0.088,0.28,0.252,0.432,0.492l1.86,2.976l1.86-2.976
|
||||
c0.152-0.24,0.284-0.398,0.396-0.475c0.112-0.075,0.242-0.113,0.39-0.113C218.743,81.561,218.977,81.661,219.297,81.861z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M123.67,105.22c0.064,0.12,0.102,0.228,0.114,0.324c0.012,0.096,0.018,0.235,0.018,0.42v6.66
|
||||
c0,0.552-0.152,0.876-0.456,0.972c-0.152,0.048-0.344,0.072-0.576,0.072c-0.232,0-0.417-0.021-0.552-0.061
|
||||
c-0.136-0.04-0.24-0.088-0.312-0.144c-0.072-0.056-0.128-0.136-0.168-0.24c-0.04-0.136-0.06-0.344-0.06-0.624v-4.02
|
||||
c-0.2,0.248-0.492,0.642-0.876,1.182c-0.384,0.54-0.628,0.878-0.732,1.014c-0.104,0.137-0.176,0.23-0.216,0.282
|
||||
c-0.041,0.052-0.138,0.124-0.294,0.216c-0.156,0.093-0.324,0.139-0.504,0.139c-0.18,0-0.344-0.042-0.492-0.126
|
||||
c-0.148-0.084-0.254-0.166-0.318-0.246l-0.096-0.133c-0.16-0.199-0.476-0.625-0.948-1.277s-0.728-1.002-0.768-1.05v4.044
|
||||
c0,0.184-0.006,0.322-0.018,0.414c-0.012,0.092-0.05,0.193-0.114,0.306c-0.12,0.216-0.432,0.324-0.936,0.324
|
||||
c-0.488,0-0.792-0.108-0.912-0.324c-0.064-0.112-0.102-0.216-0.114-0.312c-0.012-0.096-0.018-0.239-0.018-0.432v-6.66
|
||||
c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317c0.12-0.208,0.432-0.312,0.936-0.312
|
||||
c0.216,0,0.402,0.026,0.558,0.078c0.156,0.052,0.258,0.106,0.306,0.162l0.072,0.072l2.724,3.575c1.36-1.8,2.268-2.987,2.724-3.563
|
||||
c0.136-0.216,0.458-0.324,0.966-0.324C123.247,104.895,123.557,105.004,123.67,105.22z"/>
|
||||
<path class="st2" d="M125.962,105.939c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V105.939z"/>
|
||||
<path class="st2" d="M135.927,105.25c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056C135.813,105.611,135.851,105.39,135.927,105.25z
|
||||
"/>
|
||||
<path class="st2" d="M145.833,105.208c0.08-0.128,0.196-0.217,0.348-0.265c0.152-0.048,0.342-0.071,0.57-0.071
|
||||
s0.41,0.02,0.546,0.06s0.24,0.088,0.312,0.145c0.072,0.056,0.124,0.14,0.156,0.252c0.048,0.136,0.072,0.344,0.072,0.624v3.624
|
||||
c0,1.056-0.328,2.016-0.984,2.88c-0.32,0.407-0.732,0.737-1.236,0.989c-0.504,0.252-1.062,0.378-1.674,0.378
|
||||
c-0.612,0-1.168-0.128-1.668-0.384s-0.906-0.592-1.218-1.008c-0.648-0.848-0.972-1.808-0.972-2.88v-3.612
|
||||
c0-0.191,0.006-0.334,0.018-0.426c0.012-0.092,0.05-0.198,0.114-0.318c0.064-0.119,0.172-0.204,0.324-0.252
|
||||
s0.356-0.071,0.612-0.071s0.46,0.023,0.612,0.071c0.152,0.048,0.256,0.133,0.312,0.252c0.096,0.185,0.144,0.437,0.144,0.757v3.6
|
||||
c0,0.488,0.12,0.952,0.36,1.392c0.12,0.225,0.3,0.404,0.54,0.54c0.24,0.137,0.524,0.204,0.852,0.204
|
||||
c0.583,0,1.02-0.216,1.308-0.647c0.288-0.433,0.432-0.933,0.432-1.5v-3.672C145.713,105.556,145.753,105.336,145.833,105.208z"/>
|
||||
<path class="st2" d="M150.573,104.872h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C150.105,104.907,150.309,104.872,150.573,104.872z"/>
|
||||
<path class="st2" d="M162.093,111.556h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V111.556z"/>
|
||||
<path class="st2" d="M168.957,112.443c-0.208-0.256-0.312-0.485-0.312-0.689s0.172-0.475,0.516-0.811
|
||||
c0.2-0.191,0.412-0.288,0.636-0.288c0.224,0,0.536,0.2,0.936,0.601c0.112,0.136,0.271,0.266,0.48,0.39
|
||||
c0.208,0.124,0.4,0.187,0.576,0.187c0.744,0,1.116-0.305,1.116-0.912c0-0.185-0.102-0.338-0.306-0.462s-0.458-0.214-0.762-0.271
|
||||
c-0.304-0.056-0.632-0.146-0.984-0.27s-0.68-0.271-0.984-0.438s-0.558-0.434-0.762-0.798c-0.204-0.364-0.306-0.802-0.306-1.313
|
||||
c0-0.704,0.262-1.318,0.786-1.843c0.524-0.523,1.238-0.786,2.142-0.786c0.48,0,0.918,0.062,1.314,0.187
|
||||
c0.396,0.124,0.67,0.25,0.822,0.378l0.3,0.228c0.248,0.232,0.372,0.429,0.372,0.589s-0.096,0.38-0.288,0.659
|
||||
c-0.272,0.4-0.552,0.601-0.84,0.601c-0.168,0-0.376-0.08-0.624-0.24c-0.024-0.016-0.07-0.056-0.138-0.12
|
||||
c-0.068-0.063-0.13-0.115-0.186-0.156c-0.168-0.104-0.382-0.155-0.642-0.155c-0.26,0-0.476,0.062-0.648,0.186
|
||||
c-0.172,0.124-0.258,0.296-0.258,0.517c0,0.22,0.102,0.397,0.306,0.533c0.204,0.137,0.458,0.229,0.762,0.276
|
||||
c0.304,0.048,0.636,0.122,0.996,0.222c0.36,0.101,0.692,0.223,0.996,0.366c0.304,0.145,0.558,0.395,0.762,0.75
|
||||
c0.204,0.356,0.306,0.794,0.306,1.314c0,0.52-0.104,0.978-0.312,1.374c-0.208,0.396-0.48,0.701-0.816,0.918
|
||||
c-0.648,0.424-1.34,0.636-2.076,0.636c-0.376,0-0.732-0.046-1.068-0.138c-0.336-0.093-0.608-0.206-0.816-0.343
|
||||
c-0.424-0.256-0.72-0.504-0.888-0.743L168.957,112.443z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M204.553,104.854h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C204.084,104.889,204.288,104.854,204.553,104.854z"/>
|
||||
<path class="st2" d="M217.356,104.757c1.184,0,2.212,0.429,3.084,1.284c0.872,0.856,1.308,1.918,1.308,3.187
|
||||
c0,1.268-0.416,2.348-1.248,3.239c-0.832,0.893-1.856,1.338-3.072,1.338c-1.216,0-2.25-0.439-3.102-1.319s-1.278-1.928-1.278-3.145
|
||||
c0-0.664,0.12-1.285,0.36-1.865c0.24-0.58,0.56-1.066,0.96-1.458c0.4-0.393,0.86-0.7,1.38-0.925
|
||||
C216.268,104.869,216.805,104.757,217.356,104.757z M215.172,109.282c0,0.712,0.23,1.29,0.69,1.733
|
||||
c0.46,0.444,0.974,0.666,1.542,0.666c0.568,0,1.08-0.216,1.536-0.647s0.684-1.012,0.684-1.74c0-0.728-0.23-1.312-0.69-1.752
|
||||
c-0.46-0.439-0.974-0.66-1.542-0.66c-0.568,0-1.08,0.223-1.536,0.666C215.4,107.992,215.172,108.57,215.172,109.282z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M67.17,104.919c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.196,0.051,0.312,0.114
|
||||
c0.116,0.064,0.198,0.172,0.246,0.324s0.072,0.355,0.072,0.612c0,0.256-0.024,0.46-0.072,0.611
|
||||
c-0.048,0.152-0.132,0.258-0.252,0.318c-0.12,0.06-0.226,0.096-0.318,0.107c-0.092,0.013-0.234,0.019-0.426,0.019h-3.672v1.212
|
||||
h2.364c0.192,0,0.334,0.006,0.426,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.208,0.12,0.312,0.437,0.312,0.948
|
||||
c0,0.56-0.152,0.892-0.456,0.996c-0.128,0.04-0.332,0.06-0.612,0.06h-2.352v2.269c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834c0.152-0.147,0.44-0.222,0.864-0.222H67.17z"/>
|
||||
<path class="st2" d="M70.193,105.975c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V105.975z"/>
|
||||
<path class="st2" d="M82.505,105.051c0.472,0.232,0.708,0.488,0.708,0.768c0,0.129-0.06,0.32-0.18,0.576l-3.312,6.721
|
||||
c-0.088,0.176-0.222,0.317-0.402,0.426c-0.18,0.107-0.366,0.162-0.558,0.162h-0.12c-0.2,0-0.39-0.055-0.57-0.162
|
||||
c-0.18-0.108-0.314-0.25-0.402-0.426l-3.312-6.721c-0.12-0.256-0.18-0.447-0.18-0.576c0-0.279,0.236-0.535,0.708-0.768
|
||||
c0.264-0.136,0.466-0.204,0.606-0.204c0.14,0,0.246,0.017,0.318,0.048c0.072,0.032,0.14,0.089,0.204,0.168
|
||||
c0.072,0.097,0.138,0.202,0.198,0.318s0.214,0.448,0.462,0.996s0.514,1.13,0.798,1.746c0.284,0.616,0.552,1.198,0.804,1.746
|
||||
s0.394,0.854,0.426,0.918l2.4-5.256c0.064-0.152,0.12-0.272,0.168-0.36c0.144-0.216,0.32-0.324,0.528-0.324
|
||||
S82.242,104.915,82.505,105.051z"/>
|
||||
<path class="st2" d="M87.197,111.591h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V111.591z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M77.722,129.916c0.208,0.424,0.312,0.896,0.312,1.416c0,0.52-0.104,0.989-0.312,1.409
|
||||
c-0.208,0.42-0.476,0.755-0.804,1.002c-0.664,0.513-1.352,0.769-2.064,0.769h-1.5v1.355c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324h2.568c0.704,0,1.388,0.256,2.052,0.768C77.246,129.155,77.514,129.491,77.722,129.916z
|
||||
M75.575,132.124c0.232-0.177,0.348-0.44,0.348-0.792c0-0.353-0.116-0.618-0.348-0.799c-0.232-0.18-0.472-0.27-0.72-0.27h-1.5
|
||||
v2.124h1.512C75.106,132.388,75.342,132.3,75.575,132.124z"/>
|
||||
<path class="st2" d="M84.095,128.763l3.24,6.696c0.136,0.271,0.204,0.476,0.204,0.611c0,0.288-0.232,0.548-0.696,0.78
|
||||
c-0.272,0.136-0.486,0.204-0.642,0.204c-0.156,0-0.284-0.036-0.384-0.108c-0.1-0.071-0.172-0.147-0.216-0.228
|
||||
s-0.106-0.2-0.186-0.36l-0.624-1.296h-3.324l-0.624,1.296c-0.08,0.16-0.142,0.276-0.186,0.349
|
||||
c-0.044,0.071-0.116,0.146-0.216,0.222s-0.228,0.114-0.384,0.114c-0.156,0-0.37-0.068-0.642-0.204
|
||||
c-0.464-0.225-0.696-0.48-0.696-0.769c0-0.136,0.068-0.34,0.204-0.611l3.24-6.708c0.088-0.185,0.222-0.332,0.402-0.444
|
||||
c0.18-0.112,0.37-0.168,0.57-0.168C83.566,128.139,83.886,128.347,84.095,128.763z M83.122,131.643l-0.792,1.644h1.596
|
||||
L83.122,131.643z"/>
|
||||
<path class="st2" d="M89.17,135.699c-0.208-0.256-0.312-0.485-0.312-0.689s0.172-0.475,0.516-0.811
|
||||
c0.2-0.191,0.412-0.288,0.636-0.288c0.224,0,0.536,0.2,0.936,0.601c0.112,0.136,0.271,0.266,0.48,0.39
|
||||
c0.208,0.124,0.4,0.187,0.576,0.187c0.744,0,1.116-0.305,1.116-0.912c0-0.185-0.102-0.338-0.306-0.462s-0.458-0.214-0.762-0.271
|
||||
c-0.304-0.056-0.632-0.146-0.984-0.27s-0.68-0.271-0.984-0.438s-0.558-0.434-0.762-0.798c-0.204-0.364-0.306-0.802-0.306-1.313
|
||||
c0-0.704,0.262-1.318,0.786-1.843c0.524-0.523,1.238-0.786,2.142-0.786c0.48,0,0.918,0.063,1.314,0.187
|
||||
c0.396,0.124,0.67,0.25,0.822,0.378l0.3,0.228c0.248,0.232,0.372,0.429,0.372,0.589s-0.096,0.38-0.288,0.659
|
||||
c-0.272,0.4-0.552,0.601-0.84,0.601c-0.168,0-0.376-0.08-0.624-0.24c-0.024-0.016-0.07-0.056-0.138-0.12
|
||||
c-0.068-0.063-0.13-0.115-0.186-0.156c-0.168-0.104-0.382-0.155-0.642-0.155c-0.26,0-0.476,0.062-0.648,0.186
|
||||
c-0.172,0.124-0.258,0.296-0.258,0.517c0,0.22,0.102,0.397,0.306,0.533c0.204,0.137,0.458,0.229,0.762,0.276
|
||||
c0.304,0.048,0.636,0.122,0.996,0.222c0.36,0.101,0.692,0.223,0.996,0.366c0.304,0.145,0.558,0.395,0.762,0.75
|
||||
c0.204,0.356,0.306,0.794,0.306,1.314c0,0.52-0.104,0.978-0.312,1.374c-0.208,0.396-0.48,0.701-0.816,0.918
|
||||
c-0.648,0.424-1.34,0.636-2.076,0.636c-0.376,0-0.732-0.046-1.068-0.138c-0.336-0.093-0.608-0.206-0.816-0.343
|
||||
c-0.424-0.256-0.72-0.504-0.888-0.743L89.17,135.699z"/>
|
||||
<path class="st2" d="M97.21,128.128h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C96.742,128.163,96.946,128.128,97.21,128.128z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M135.291,128.001c1.184,0,2.212,0.429,3.084,1.284c0.872,0.856,1.308,1.918,1.308,3.187
|
||||
c0,1.268-0.416,2.348-1.248,3.239c-0.832,0.893-1.856,1.338-3.072,1.338c-1.216,0-2.25-0.439-3.102-1.319s-1.278-1.928-1.278-3.145
|
||||
c0-0.664,0.12-1.285,0.36-1.865c0.24-0.58,0.56-1.066,0.96-1.458c0.4-0.393,0.86-0.7,1.38-0.925
|
||||
C134.203,128.114,134.739,128.001,135.291,128.001z M133.107,132.526c0,0.712,0.23,1.29,0.69,1.733
|
||||
c0.46,0.444,0.974,0.666,1.542,0.666c0.568,0,1.08-0.216,1.536-0.647s0.684-1.012,0.684-1.74c0-0.728-0.23-1.312-0.69-1.752
|
||||
c-0.46-0.439-0.974-0.66-1.542-0.66c-0.568,0-1.08,0.223-1.536,0.666C133.335,131.236,133.107,131.814,133.107,132.526z"/>
|
||||
<path class="st2" d="M147.345,128.476c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056
|
||||
C147.231,128.837,147.269,128.616,147.345,128.476z"/>
|
||||
<path class="st2" d="M153.627,134.782h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V134.782z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M180.068,128.085h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C179.6,128.12,179.804,128.085,180.068,128.085z"/>
|
||||
<path class="st2" d="M194.9,128.421c0.064-0.12,0.172-0.204,0.324-0.252c0.152-0.049,0.344-0.072,0.576-0.072
|
||||
s0.416,0.02,0.552,0.06c0.136,0.04,0.24,0.089,0.312,0.145c0.072,0.056,0.128,0.136,0.168,0.24c0.04,0.136,0.06,0.344,0.06,0.624
|
||||
v6.659c0,0.185-0.006,0.322-0.018,0.414c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.148-0.984-0.444c-0.048-0.136-0.072-0.344-0.072-0.624v-2.436h-3.18v2.447c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v2.447h3.18v-2.46
|
||||
c0-0.184,0.006-0.321,0.018-0.414C194.798,128.647,194.836,128.541,194.9,128.421z"/>
|
||||
<path class="st2" d="M205.784,135.405c0.12,0.288,0.18,0.496,0.18,0.624c0,0.305-0.248,0.561-0.744,0.769
|
||||
c-0.256,0.111-0.462,0.168-0.618,0.168c-0.156,0-0.284-0.038-0.384-0.114s-0.174-0.154-0.222-0.234
|
||||
c-0.08-0.151-0.392-0.876-0.936-2.172l-0.372,0.024h-1.512v1.355c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324h2.592c0.704,0,1.388,0.256,2.052,0.768c0.32,0.248,0.584,0.584,0.792,1.009
|
||||
c0.208,0.424,0.312,0.896,0.312,1.416c0,0.903-0.3,1.647-0.9,2.231C205.143,133.945,205.415,134.573,205.784,135.405z
|
||||
M201.176,132.345h1.536c0.232,0,0.464-0.088,0.696-0.264c0.232-0.177,0.348-0.44,0.348-0.792c0-0.353-0.116-0.618-0.348-0.799
|
||||
c-0.232-0.18-0.472-0.27-0.72-0.27h-1.512V132.345z"/>
|
||||
<path class="st2" d="M209.948,134.769h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V134.769z"/>
|
||||
<path class="st2" d="M218.804,134.769h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V134.769z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M129.137,151.342h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C128.669,151.377,128.873,151.342,129.137,151.342z"/>
|
||||
<path class="st2" d="M149.056,151.402c0.536,0.192,0.804,0.448,0.804,0.768c0,0.104-0.048,0.301-0.144,0.589l-2.304,6.659
|
||||
c-0.016,0.057-0.044,0.125-0.084,0.204c-0.04,0.08-0.146,0.187-0.318,0.318c-0.172,0.132-0.376,0.198-0.612,0.198
|
||||
c-0.236,0-0.44-0.066-0.612-0.198s-0.286-0.262-0.342-0.39l-1.404-4.141c-0.888,2.624-1.34,3.96-1.356,4.008
|
||||
c-0.016,0.049-0.052,0.116-0.108,0.204c-0.056,0.089-0.12,0.168-0.192,0.24c-0.184,0.185-0.404,0.276-0.66,0.276
|
||||
s-0.466-0.061-0.63-0.181c-0.164-0.119-0.274-0.239-0.33-0.359l-0.084-0.181l-2.316-6.659c-0.088-0.265-0.132-0.46-0.132-0.589
|
||||
c0-0.319,0.268-0.571,0.804-0.756c0.232-0.079,0.442-0.12,0.63-0.12s0.332,0.064,0.432,0.192s0.19,0.324,0.27,0.588l1.32,4.008
|
||||
l1.308-3.947c0.112-0.336,0.316-0.568,0.612-0.696c0.128-0.056,0.294-0.084,0.498-0.084c0.204,0,0.394,0.065,0.57,0.198
|
||||
c0.176,0.132,0.288,0.262,0.336,0.39l1.38,4.164l1.32-4.032c0.064-0.184,0.116-0.319,0.156-0.408
|
||||
c0.04-0.088,0.114-0.174,0.222-0.258s0.242-0.126,0.402-0.126S148.841,151.322,149.056,151.402z"/>
|
||||
<path class="st2" d="M155.848,151.245c1.184,0,2.212,0.429,3.084,1.284c0.872,0.856,1.308,1.918,1.308,3.187
|
||||
c0,1.268-0.416,2.348-1.248,3.239c-0.832,0.893-1.856,1.338-3.072,1.338c-1.216,0-2.25-0.439-3.102-1.319s-1.278-1.928-1.278-3.145
|
||||
c0-0.664,0.12-1.285,0.36-1.865c0.24-0.58,0.56-1.066,0.96-1.458c0.4-0.393,0.86-0.7,1.38-0.925
|
||||
C154.761,151.358,155.297,151.245,155.848,151.245z M153.664,155.77c0,0.712,0.23,1.29,0.69,1.733
|
||||
c0.46,0.444,0.974,0.666,1.542,0.666c0.568,0,1.08-0.216,1.536-0.647s0.684-1.012,0.684-1.74c0-0.728-0.23-1.312-0.69-1.752
|
||||
c-0.46-0.439-0.974-0.66-1.542-0.66c-0.568,0-1.08,0.223-1.536,0.666C153.892,154.48,153.664,155.058,153.664,155.77z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M73.833,151.354c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.196,0.051,0.312,0.114
|
||||
c0.116,0.064,0.198,0.172,0.246,0.324s0.072,0.355,0.072,0.612c0,0.256-0.024,0.46-0.072,0.611
|
||||
c-0.048,0.152-0.132,0.258-0.252,0.318c-0.12,0.06-0.226,0.096-0.318,0.107c-0.092,0.013-0.234,0.019-0.426,0.019h-3.672v1.212
|
||||
H72.5c0.192,0,0.334,0.006,0.426,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.208,0.12,0.312,0.437,0.312,0.948
|
||||
c0,0.56-0.152,0.892-0.456,0.996c-0.128,0.04-0.332,0.06-0.612,0.06h-2.352v2.269c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834c0.152-0.147,0.44-0.222,0.864-0.222H73.833z"/>
|
||||
<path class="st2" d="M80.984,151.245c1.184,0,2.212,0.429,3.084,1.284c0.872,0.856,1.308,1.918,1.308,3.187
|
||||
c0,1.268-0.416,2.348-1.248,3.239c-0.832,0.893-1.856,1.338-3.072,1.338c-1.216,0-2.25-0.439-3.102-1.319s-1.278-1.928-1.278-3.145
|
||||
c0-0.664,0.12-1.285,0.36-1.865c0.24-0.58,0.56-1.066,0.96-1.458c0.4-0.393,0.86-0.7,1.38-0.925
|
||||
C79.896,151.358,80.433,151.245,80.984,151.245z M78.8,155.77c0,0.712,0.23,1.29,0.69,1.733c0.46,0.444,0.974,0.666,1.542,0.666
|
||||
c0.568,0,1.08-0.216,1.536-0.647s0.684-1.012,0.684-1.74c0-0.728-0.23-1.312-0.69-1.752c-0.46-0.439-0.974-0.66-1.542-0.66
|
||||
c-0.568,0-1.08,0.223-1.536,0.666C79.028,154.48,78.8,155.058,78.8,155.77z"/>
|
||||
<path class="st2" d="M93.104,151.678c0.08-0.128,0.196-0.217,0.348-0.265c0.152-0.048,0.342-0.071,0.57-0.071s0.41,0.02,0.546,0.06
|
||||
s0.24,0.088,0.312,0.145c0.072,0.056,0.124,0.14,0.156,0.252c0.048,0.136,0.072,0.344,0.072,0.624v3.624
|
||||
c0,1.056-0.328,2.016-0.984,2.88c-0.32,0.407-0.732,0.737-1.236,0.989c-0.504,0.252-1.062,0.378-1.674,0.378
|
||||
c-0.612,0-1.168-0.128-1.668-0.384s-0.906-0.592-1.218-1.008c-0.648-0.848-0.972-1.808-0.972-2.88v-3.612
|
||||
c0-0.191,0.006-0.334,0.018-0.426c0.012-0.092,0.05-0.198,0.114-0.318c0.064-0.119,0.172-0.204,0.324-0.252
|
||||
s0.356-0.071,0.612-0.071s0.46,0.023,0.612,0.071c0.152,0.048,0.256,0.133,0.312,0.252c0.096,0.185,0.144,0.437,0.144,0.757v3.6
|
||||
c0,0.488,0.12,0.952,0.36,1.392c0.12,0.225,0.3,0.404,0.54,0.54c0.24,0.137,0.524,0.204,0.852,0.204
|
||||
c0.583,0,1.02-0.216,1.308-0.647c0.288-0.433,0.432-0.933,0.432-1.5v-3.672C92.984,152.026,93.024,151.806,93.104,151.678z"/>
|
||||
<path class="st2" d="M104,158.661c0.12,0.288,0.18,0.496,0.18,0.624c0,0.305-0.248,0.561-0.744,0.769
|
||||
c-0.256,0.111-0.462,0.168-0.618,0.168c-0.156,0-0.284-0.038-0.384-0.114s-0.174-0.154-0.222-0.234
|
||||
c-0.08-0.151-0.392-0.876-0.936-2.172l-0.372,0.024h-1.512v1.355c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324h2.592c0.704,0,1.388,0.256,2.052,0.768c0.32,0.248,0.584,0.584,0.792,1.009
|
||||
c0.208,0.424,0.312,0.896,0.312,1.416c0,0.903-0.3,1.647-0.9,2.231C103.36,157.201,103.632,157.829,104,158.661z M99.393,155.602
|
||||
h1.536c0.232,0,0.464-0.088,0.696-0.264c0.232-0.177,0.348-0.44,0.348-0.792c0-0.353-0.116-0.618-0.348-0.799
|
||||
c-0.232-0.18-0.472-0.27-0.72-0.27h-1.512V155.602z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M191.894,151.407c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.196,0.051,0.312,0.114
|
||||
c0.116,0.064,0.198,0.172,0.246,0.324s0.072,0.355,0.072,0.612c0,0.256-0.024,0.46-0.072,0.611
|
||||
c-0.048,0.152-0.132,0.258-0.252,0.318c-0.12,0.06-0.226,0.096-0.318,0.107c-0.092,0.013-0.234,0.019-0.426,0.019h-3.672v1.212
|
||||
h2.364c0.192,0,0.334,0.006,0.426,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.208,0.12,0.312,0.437,0.312,0.948
|
||||
c0,0.56-0.152,0.892-0.456,0.996c-0.128,0.04-0.332,0.06-0.612,0.06h-2.352v2.269c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834c0.152-0.147,0.44-0.222,0.864-0.222H191.894z"/>
|
||||
<path class="st2" d="M194.918,152.463c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V152.463z"/>
|
||||
<path class="st2" d="M207.23,151.539c0.472,0.232,0.708,0.488,0.708,0.768c0,0.129-0.06,0.32-0.18,0.576l-3.312,6.721
|
||||
c-0.088,0.176-0.222,0.317-0.402,0.426c-0.18,0.107-0.366,0.162-0.558,0.162h-0.12c-0.2,0-0.39-0.055-0.57-0.162
|
||||
c-0.18-0.108-0.314-0.25-0.402-0.426l-3.312-6.721c-0.12-0.256-0.18-0.447-0.18-0.576c0-0.279,0.236-0.535,0.708-0.768
|
||||
c0.264-0.136,0.466-0.204,0.606-0.204c0.14,0,0.246,0.017,0.318,0.048c0.072,0.032,0.14,0.089,0.204,0.168
|
||||
c0.072,0.097,0.138,0.202,0.198,0.318s0.214,0.448,0.462,0.996s0.514,1.13,0.798,1.746c0.284,0.616,0.552,1.198,0.804,1.746
|
||||
s0.394,0.854,0.426,0.918l2.4-5.256c0.064-0.152,0.12-0.272,0.168-0.36c0.144-0.216,0.32-0.324,0.528-0.324
|
||||
S206.966,151.404,207.23,151.539z"/>
|
||||
<path class="st2" d="M211.922,158.079h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V158.079z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M134.827,182.229c-0.208-0.256-0.312-0.485-0.312-0.689s0.172-0.475,0.516-0.811
|
||||
c0.2-0.191,0.412-0.288,0.636-0.288c0.224,0,0.536,0.2,0.936,0.601c0.112,0.136,0.271,0.266,0.48,0.39
|
||||
c0.208,0.124,0.4,0.187,0.576,0.187c0.744,0,1.116-0.305,1.116-0.912c0-0.185-0.102-0.338-0.306-0.462s-0.458-0.214-0.762-0.271
|
||||
c-0.304-0.056-0.632-0.146-0.984-0.27s-0.68-0.271-0.984-0.438s-0.558-0.434-0.762-0.798c-0.204-0.364-0.306-0.802-0.306-1.313
|
||||
c0-0.704,0.262-1.318,0.786-1.843c0.524-0.523,1.238-0.786,2.142-0.786c0.48,0,0.918,0.062,1.314,0.187
|
||||
c0.396,0.124,0.67,0.25,0.822,0.378l0.3,0.228c0.248,0.232,0.372,0.429,0.372,0.589s-0.096,0.38-0.288,0.659
|
||||
c-0.272,0.4-0.552,0.601-0.84,0.601c-0.168,0-0.376-0.08-0.624-0.24c-0.024-0.016-0.07-0.056-0.138-0.12
|
||||
c-0.068-0.063-0.13-0.115-0.186-0.156c-0.168-0.104-0.382-0.155-0.642-0.155c-0.26,0-0.476,0.062-0.648,0.186
|
||||
c-0.172,0.124-0.258,0.296-0.258,0.517c0,0.22,0.102,0.397,0.306,0.533c0.204,0.137,0.458,0.229,0.762,0.276
|
||||
c0.304,0.048,0.636,0.122,0.996,0.222c0.36,0.101,0.692,0.223,0.996,0.366c0.304,0.145,0.558,0.395,0.762,0.75
|
||||
c0.204,0.356,0.306,0.794,0.306,1.314c0,0.52-0.104,0.978-0.312,1.374c-0.208,0.396-0.48,0.701-0.816,0.918
|
||||
c-0.648,0.424-1.34,0.636-2.076,0.636c-0.376,0-0.732-0.046-1.068-0.138c-0.336-0.093-0.608-0.206-0.816-0.343
|
||||
c-0.424-0.256-0.72-0.504-0.888-0.743L134.827,182.229z"/>
|
||||
<path class="st2" d="M142.891,175.725c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V175.725z"/>
|
||||
<path class="st2" d="M152.587,179.013l2.412,2.652c0.271,0.304,0.408,0.56,0.408,0.768s-0.154,0.452-0.462,0.732
|
||||
s-0.568,0.42-0.78,0.42c-0.212,0-0.458-0.16-0.738-0.48l-2.28-2.615l-2.28,2.615c-0.288,0.32-0.534,0.48-0.738,0.48
|
||||
s-0.464-0.142-0.78-0.426s-0.474-0.526-0.474-0.727c0-0.199,0.14-0.456,0.42-0.768l2.412-2.652l-2.412-2.651
|
||||
c-0.28-0.296-0.42-0.549-0.42-0.757s0.156-0.453,0.468-0.737s0.574-0.427,0.786-0.427s0.458,0.16,0.738,0.48l2.28,2.616l2.28-2.616
|
||||
c0.288-0.32,0.534-0.48,0.738-0.48c0.204,0,0.462,0.141,0.774,0.421c0.312,0.279,0.468,0.527,0.468,0.743
|
||||
c0,0.217-0.136,0.469-0.408,0.757L152.587,179.013z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M65.227,182.187c-0.208-0.256-0.312-0.485-0.312-0.689s0.172-0.475,0.516-0.811
|
||||
c0.2-0.191,0.412-0.288,0.636-0.288c0.224,0,0.536,0.2,0.936,0.601c0.112,0.136,0.271,0.266,0.48,0.39
|
||||
c0.208,0.124,0.4,0.187,0.576,0.187c0.744,0,1.116-0.305,1.116-0.912c0-0.185-0.102-0.338-0.306-0.462s-0.458-0.214-0.762-0.271
|
||||
c-0.304-0.056-0.632-0.146-0.984-0.27s-0.68-0.271-0.984-0.438s-0.558-0.434-0.762-0.798c-0.204-0.364-0.306-0.802-0.306-1.313
|
||||
c0-0.704,0.262-1.318,0.786-1.843c0.524-0.523,1.238-0.786,2.142-0.786c0.48,0,0.918,0.062,1.314,0.187
|
||||
c0.396,0.124,0.67,0.25,0.822,0.378l0.3,0.228c0.248,0.232,0.372,0.429,0.372,0.589s-0.096,0.38-0.288,0.659
|
||||
c-0.272,0.4-0.552,0.601-0.84,0.601c-0.168,0-0.376-0.08-0.624-0.24c-0.024-0.016-0.07-0.056-0.138-0.12
|
||||
c-0.068-0.063-0.13-0.115-0.186-0.156c-0.168-0.104-0.382-0.155-0.642-0.155c-0.26,0-0.476,0.062-0.648,0.186
|
||||
c-0.172,0.124-0.258,0.296-0.258,0.517c0,0.22,0.102,0.397,0.306,0.533c0.204,0.137,0.458,0.229,0.762,0.276
|
||||
c0.304,0.048,0.636,0.122,0.996,0.222c0.36,0.101,0.692,0.223,0.996,0.366c0.304,0.145,0.558,0.395,0.762,0.75
|
||||
c0.204,0.356,0.306,0.794,0.306,1.314c0,0.52-0.104,0.978-0.312,1.374c-0.208,0.396-0.48,0.701-0.816,0.918
|
||||
c-0.648,0.424-1.34,0.636-2.076,0.636c-0.376,0-0.732-0.046-1.068-0.138c-0.336-0.093-0.608-0.206-0.816-0.343
|
||||
c-0.424-0.256-0.72-0.504-0.888-0.743L65.227,182.187z"/>
|
||||
<path class="st2" d="M75.415,181.3h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V181.3z"/>
|
||||
<path class="st2" d="M90.175,174.759c0.472,0.232,0.708,0.488,0.708,0.768c0,0.129-0.06,0.32-0.18,0.576l-3.312,6.721
|
||||
c-0.088,0.176-0.222,0.317-0.402,0.426c-0.18,0.107-0.366,0.162-0.558,0.162h-0.12c-0.2,0-0.39-0.055-0.57-0.162
|
||||
c-0.18-0.108-0.314-0.25-0.402-0.426l-3.312-6.721c-0.12-0.256-0.18-0.447-0.18-0.576c0-0.279,0.236-0.535,0.708-0.768
|
||||
c0.264-0.136,0.466-0.204,0.606-0.204c0.14,0,0.246,0.017,0.318,0.048c0.072,0.032,0.14,0.089,0.204,0.168
|
||||
c0.072,0.097,0.138,0.202,0.198,0.318s0.214,0.448,0.462,0.996s0.514,1.13,0.798,1.746c0.284,0.616,0.552,1.198,0.804,1.746
|
||||
s0.394,0.854,0.426,0.918l2.4-5.256c0.064-0.152,0.12-0.272,0.168-0.36c0.144-0.216,0.32-0.324,0.528-0.324
|
||||
S89.911,174.624,90.175,174.759z"/>
|
||||
<path class="st2" d="M94.866,181.3h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V181.3z"/>
|
||||
<path class="st2" d="M107.281,174.994c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056
|
||||
C107.166,175.355,107.204,175.134,107.281,174.994z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M183.194,181.305h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V181.305z"/>
|
||||
<path class="st2" d="M189.926,175.689c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V175.689z"/>
|
||||
<path class="st2" d="M198.794,178.126h2.112c0.432,0.016,0.696,0.128,0.792,0.336c0.08,0.151,0.12,0.376,0.12,0.672v2.64
|
||||
c0,0.257-0.112,0.5-0.336,0.732c-0.672,0.696-1.68,1.044-3.024,1.044c-1.192,0-2.228-0.45-3.108-1.351
|
||||
c-0.88-0.899-1.32-1.985-1.32-3.258c0-1.271,0.448-2.334,1.344-3.186c0.896-0.853,1.952-1.278,3.168-1.278
|
||||
c0.944,0,1.836,0.312,2.676,0.937c0.216,0.16,0.324,0.338,0.324,0.533c0,0.196-0.092,0.423-0.276,0.679
|
||||
c-0.312,0.424-0.596,0.636-0.852,0.636c-0.152,0-0.396-0.11-0.732-0.33s-0.736-0.33-1.2-0.33c-0.608,0-1.148,0.214-1.62,0.643
|
||||
c-0.472,0.428-0.708,0.987-0.708,1.68s0.24,1.28,0.72,1.764c0.48,0.484,1.024,0.727,1.632,0.727c0.44,0,0.836-0.072,1.188-0.217
|
||||
v-1.308h-0.948c-0.248,0-0.424-0.032-0.528-0.096c-0.104-0.064-0.172-0.158-0.204-0.282c-0.032-0.124-0.048-0.292-0.048-0.504
|
||||
s0.018-0.382,0.054-0.51s0.102-0.217,0.198-0.265C198.362,178.162,198.554,178.126,198.794,178.126z"/>
|
||||
<path class="st2" d="M209.414,174.958c0.064-0.12,0.172-0.204,0.324-0.252c0.152-0.049,0.344-0.072,0.576-0.072
|
||||
s0.416,0.02,0.552,0.06c0.136,0.04,0.24,0.089,0.312,0.145c0.072,0.056,0.128,0.136,0.168,0.24c0.04,0.136,0.06,0.344,0.06,0.624
|
||||
v6.659c0,0.185-0.006,0.322-0.018,0.414c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.148-0.984-0.444c-0.048-0.136-0.072-0.344-0.072-0.624v-2.436h-3.18v2.447c0,0.185-0.006,0.322-0.018,0.414
|
||||
c-0.012,0.093-0.05,0.198-0.114,0.318c-0.112,0.216-0.424,0.324-0.936,0.324c-0.56,0-0.888-0.148-0.984-0.444
|
||||
c-0.048-0.136-0.072-0.344-0.072-0.624v-6.66c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v2.447h3.18v-2.46
|
||||
c0-0.184,0.006-0.321,0.018-0.414C209.312,175.183,209.35,175.078,209.414,174.958z"/>
|
||||
<path class="st2" d="M214.142,174.622h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C213.674,174.657,213.878,174.622,214.142,174.622z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M66.912,198.226c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056C66.798,198.587,66.836,198.365,66.912,198.226z"
|
||||
/>
|
||||
<path class="st2" d="M71.07,198.915c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624v6.672
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612V198.915z"/>
|
||||
<path class="st2" d="M81.035,198.226c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056C80.921,198.587,80.959,198.365,81.035,198.226z"
|
||||
/>
|
||||
<path class="st2" d="M87.317,204.531h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V204.531z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M199.485,197.854h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C199.017,197.889,199.221,197.854,199.485,197.854z"/>
|
||||
<path class="st2" d="M211.005,204.537h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V204.537z"/>
|
||||
<path class="st2" d="M223.419,198.232c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056
|
||||
C223.305,198.593,223.343,198.371,223.419,198.232z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M118.73,204.568h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V204.568z"/>
|
||||
<path class="st2" d="M127.586,204.915h3.264c0.264,0,0.456,0.03,0.576,0.091c0.12,0.06,0.2,0.153,0.24,0.281s0.06,0.299,0.06,0.511
|
||||
s-0.02,0.382-0.06,0.51s-0.108,0.216-0.204,0.264c-0.152,0.08-0.36,0.12-0.624,0.12h-4.32c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624V204.915z"/>
|
||||
<path class="st2" d="M135.829,204.568h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V204.568z"/>
|
||||
<path class="st2" d="M150.589,198.028c0.472,0.232,0.708,0.488,0.708,0.768c0,0.129-0.06,0.32-0.18,0.576l-3.312,6.721
|
||||
c-0.088,0.176-0.222,0.317-0.402,0.426c-0.18,0.107-0.366,0.162-0.558,0.162h-0.12c-0.2,0-0.39-0.055-0.57-0.162
|
||||
c-0.18-0.108-0.314-0.25-0.402-0.426l-3.312-6.721c-0.12-0.256-0.18-0.447-0.18-0.576c0-0.279,0.236-0.535,0.708-0.768
|
||||
c0.264-0.136,0.466-0.204,0.606-0.204c0.14,0,0.246,0.017,0.318,0.048c0.072,0.032,0.14,0.089,0.204,0.168
|
||||
c0.072,0.097,0.138,0.202,0.198,0.318s0.214,0.448,0.462,0.996s0.514,1.13,0.798,1.746c0.284,0.616,0.552,1.198,0.804,1.746
|
||||
s0.394,0.854,0.426,0.918l2.4-5.256c0.064-0.152,0.12-0.272,0.168-0.36c0.144-0.216,0.32-0.324,0.528-0.324
|
||||
S150.325,197.892,150.589,198.028z"/>
|
||||
<path class="st2" d="M155.281,204.568h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V204.568z"/>
|
||||
<path class="st2" d="M167.695,198.262c0.076-0.141,0.19-0.234,0.342-0.282s0.342-0.072,0.57-0.072c0.228,0,0.412,0.021,0.552,0.061
|
||||
s0.244,0.088,0.312,0.144s0.118,0.141,0.15,0.252c0.048,0.128,0.072,0.332,0.072,0.612v6.66c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.312,0-0.528-0.024-0.648-0.072
|
||||
c-0.12-0.048-0.22-0.124-0.3-0.228c-1.8-2.4-2.984-3.968-3.552-4.704v3.948c0,0.191-0.006,0.332-0.018,0.42
|
||||
c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324c-0.496,0-0.8-0.108-0.912-0.324
|
||||
c-0.064-0.12-0.102-0.228-0.114-0.324c-0.012-0.096-0.018-0.235-0.018-0.42v-6.695c0-0.305,0.038-0.526,0.114-0.666
|
||||
c0.076-0.141,0.19-0.234,0.342-0.282s0.348-0.072,0.588-0.072c0.24,0,0.43,0.022,0.57,0.066c0.14,0.044,0.238,0.094,0.294,0.149
|
||||
c0.032,0.024,0.124,0.129,0.276,0.312c1.688,2.296,2.816,3.812,3.384,4.548v-4.056
|
||||
C167.581,198.623,167.619,198.402,167.695,198.262z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M164.878,220.996c1.184,0,2.212,0.429,3.084,1.284c0.872,0.856,1.308,1.918,1.308,3.187
|
||||
c0,1.268-0.416,2.348-1.248,3.239c-0.832,0.893-1.856,1.338-3.072,1.338c-1.216,0-2.25-0.439-3.102-1.319s-1.278-1.928-1.278-3.145
|
||||
c0-0.664,0.12-1.285,0.36-1.865c0.24-0.58,0.56-1.066,0.96-1.458c0.4-0.393,0.86-0.7,1.38-0.925
|
||||
C163.79,221.108,164.326,220.996,164.878,220.996z M162.694,225.52c0,0.712,0.23,1.29,0.69,1.733
|
||||
c0.46,0.444,0.974,0.666,1.542,0.666c0.568,0,1.08-0.216,1.536-0.647s0.684-1.012,0.684-1.74c0-0.728-0.23-1.312-0.69-1.752
|
||||
c-0.46-0.439-0.974-0.66-1.542-0.66c-0.568,0-1.08,0.223-1.536,0.666C162.922,224.23,162.694,224.808,162.694,225.52z"/>
|
||||
<path class="st2" d="M173.11,221.356c0.136,0.136,0.204,0.368,0.204,0.696v0.191c0,0.2-0.008,0.349-0.024,0.444
|
||||
c-0.056,0.704-0.264,1.308-0.624,1.812s-0.816,0.757-1.368,0.757c-0.056,0-0.106-0.042-0.15-0.126s-0.066-0.194-0.066-0.33
|
||||
c0-0.137,0.018-0.242,0.054-0.318c0.036-0.076,0.076-0.12,0.12-0.132s0.078-0.021,0.102-0.024s0.068-0.023,0.132-0.06
|
||||
c0.064-0.036,0.12-0.086,0.168-0.15c0.128-0.168,0.2-0.428,0.216-0.78c-0.272-0.039-0.474-0.127-0.606-0.264
|
||||
c-0.132-0.136-0.198-0.424-0.198-0.864c0-0.319,0.04-0.558,0.12-0.714c0.08-0.155,0.202-0.26,0.366-0.312
|
||||
c0.164-0.052,0.418-0.078,0.762-0.078C172.662,221.104,172.925,221.188,173.11,221.356z"/>
|
||||
<path class="st2" d="M180.79,227.596l0.216-0.156c0.272-0.16,0.464-0.24,0.576-0.24c0.248,0,0.516,0.225,0.804,0.672
|
||||
c0.176,0.28,0.264,0.504,0.264,0.672s-0.054,0.309-0.162,0.421c-0.108,0.111-0.234,0.212-0.378,0.3s-0.282,0.172-0.414,0.252
|
||||
c-0.132,0.08-0.402,0.184-0.81,0.312c-0.408,0.128-0.802,0.192-1.182,0.192c-0.38,0-0.764-0.05-1.152-0.15
|
||||
c-0.388-0.1-0.788-0.268-1.2-0.504c-0.412-0.235-0.782-0.523-1.11-0.864c-0.328-0.34-0.598-0.775-0.81-1.308
|
||||
c-0.212-0.532-0.318-1.11-0.318-1.734s0.104-1.189,0.312-1.697s0.474-0.929,0.798-1.261c0.324-0.331,0.694-0.609,1.11-0.834
|
||||
c0.784-0.432,1.572-0.647,2.364-0.647c0.376,0,0.758,0.058,1.146,0.174c0.388,0.116,0.682,0.234,0.882,0.354l0.288,0.168
|
||||
c0.144,0.088,0.256,0.16,0.336,0.216c0.208,0.168,0.312,0.357,0.312,0.569c0,0.213-0.084,0.435-0.252,0.666
|
||||
c-0.312,0.433-0.592,0.648-0.84,0.648c-0.144,0-0.348-0.088-0.612-0.264c-0.336-0.272-0.784-0.408-1.344-0.408
|
||||
c-0.52,0-1.032,0.18-1.536,0.54c-0.24,0.176-0.44,0.424-0.6,0.744c-0.16,0.319-0.24,0.682-0.24,1.086
|
||||
c0,0.403,0.08,0.766,0.24,1.086c0.16,0.32,0.364,0.572,0.612,0.756c0.488,0.353,0.996,0.528,1.524,0.528
|
||||
c0.248,0,0.482-0.032,0.702-0.097C180.536,227.724,180.694,227.66,180.79,227.596z"/>
|
||||
<path class="st2" d="M186.765,228.124h3.264c0.264,0,0.456,0.03,0.576,0.091c0.12,0.06,0.2,0.153,0.24,0.281s0.06,0.299,0.06,0.511
|
||||
s-0.02,0.382-0.06,0.51s-0.108,0.216-0.204,0.264c-0.152,0.08-0.36,0.12-0.624,0.12h-4.32c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624V228.124z"/>
|
||||
<path class="st2" d="M197.013,220.996c1.184,0,2.212,0.429,3.084,1.284c0.872,0.856,1.308,1.918,1.308,3.187
|
||||
c0,1.268-0.416,2.348-1.248,3.239c-0.832,0.893-1.856,1.338-3.072,1.338c-1.216,0-2.25-0.439-3.102-1.319s-1.278-1.928-1.278-3.145
|
||||
c0-0.664,0.12-1.285,0.36-1.865c0.24-0.58,0.56-1.066,0.96-1.458c0.4-0.393,0.86-0.7,1.38-0.925
|
||||
C195.925,221.108,196.462,220.996,197.013,220.996z M194.829,225.52c0,0.712,0.23,1.29,0.69,1.733
|
||||
c0.46,0.444,0.974,0.666,1.542,0.666c0.568,0,1.08-0.216,1.536-0.647s0.684-1.012,0.684-1.74c0-0.728-0.23-1.312-0.69-1.752
|
||||
c-0.46-0.439-0.974-0.66-1.542-0.66c-0.568,0-1.08,0.223-1.536,0.666C195.057,224.23,194.829,224.808,194.829,225.52z"/>
|
||||
<path class="st2" d="M208.882,227.596l0.216-0.156c0.272-0.16,0.464-0.24,0.576-0.24c0.248,0,0.516,0.225,0.804,0.672
|
||||
c0.176,0.28,0.264,0.504,0.264,0.672s-0.054,0.309-0.162,0.421c-0.108,0.111-0.234,0.212-0.378,0.3s-0.282,0.172-0.414,0.252
|
||||
c-0.132,0.08-0.402,0.184-0.81,0.312c-0.408,0.128-0.802,0.192-1.182,0.192c-0.38,0-0.764-0.05-1.152-0.15
|
||||
c-0.388-0.1-0.788-0.268-1.2-0.504c-0.412-0.235-0.782-0.523-1.11-0.864c-0.328-0.34-0.598-0.775-0.81-1.308
|
||||
c-0.212-0.532-0.318-1.11-0.318-1.734s0.104-1.189,0.312-1.697s0.474-0.929,0.798-1.261c0.324-0.331,0.694-0.609,1.11-0.834
|
||||
c0.784-0.432,1.572-0.647,2.364-0.647c0.376,0,0.758,0.058,1.146,0.174c0.388,0.116,0.682,0.234,0.882,0.354l0.288,0.168
|
||||
c0.144,0.088,0.256,0.16,0.336,0.216c0.208,0.168,0.312,0.357,0.312,0.569c0,0.213-0.084,0.435-0.252,0.666
|
||||
c-0.312,0.433-0.592,0.648-0.84,0.648c-0.144,0-0.348-0.088-0.612-0.264c-0.336-0.272-0.784-0.408-1.344-0.408
|
||||
c-0.52,0-1.032,0.18-1.536,0.54c-0.24,0.176-0.44,0.424-0.6,0.744c-0.16,0.319-0.24,0.682-0.24,1.086
|
||||
c0,0.403,0.08,0.766,0.24,1.086c0.16,0.32,0.364,0.572,0.612,0.756c0.488,0.353,0.996,0.528,1.524,0.528
|
||||
c0.248,0,0.482-0.032,0.702-0.097C208.628,227.724,208.785,227.66,208.882,227.596z"/>
|
||||
<path class="st2" d="M216.501,225.484c1.224,1.176,2.092,2.061,2.604,2.652c0.264,0.296,0.396,0.546,0.396,0.75
|
||||
s-0.16,0.443-0.48,0.72c-0.32,0.276-0.582,0.414-0.786,0.414s-0.45-0.168-0.738-0.504l-2.64-3.013v2.341
|
||||
c0,0.191-0.006,0.332-0.018,0.42c-0.012,0.088-0.05,0.191-0.114,0.312c-0.112,0.216-0.424,0.324-0.936,0.324
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.184,0.006-0.321,0.018-0.414
|
||||
c0.012-0.092,0.05-0.197,0.114-0.317c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444
|
||||
c0.04,0.136,0.06,0.344,0.06,0.624v2.292c1.088-1.225,1.968-2.229,2.64-3.013c0.28-0.328,0.524-0.492,0.732-0.492
|
||||
s0.472,0.139,0.792,0.414c0.32,0.276,0.48,0.517,0.48,0.721s-0.12,0.445-0.36,0.726c-0.464,0.536-1.184,1.272-2.16,2.208
|
||||
L216.501,225.484z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M71.187,221.128h6.672c0.256,0,0.444,0.029,0.564,0.09c0.12,0.06,0.2,0.154,0.24,0.282
|
||||
c0.04,0.128,0.06,0.296,0.06,0.504s-0.02,0.374-0.06,0.498c-0.041,0.124-0.108,0.21-0.204,0.258
|
||||
c-0.144,0.072-0.348,0.107-0.612,0.107h-2.292v6.036c0,0.185-0.006,0.32-0.018,0.408c-0.012,0.088-0.048,0.19-0.108,0.306
|
||||
c-0.06,0.116-0.166,0.198-0.318,0.246s-0.352,0.072-0.6,0.072s-0.446-0.024-0.594-0.072c-0.148-0.048-0.252-0.13-0.312-0.246
|
||||
c-0.06-0.115-0.096-0.22-0.108-0.312c-0.012-0.092-0.018-0.23-0.018-0.414v-6.024h-2.304c-0.256,0-0.444-0.029-0.564-0.09
|
||||
c-0.12-0.06-0.2-0.153-0.24-0.282c-0.041-0.128-0.06-0.296-0.06-0.504s0.02-0.374,0.06-0.498c0.04-0.124,0.108-0.21,0.204-0.258
|
||||
C70.719,221.163,70.923,221.128,71.187,221.128z"/>
|
||||
<path class="st2" d="M91.106,221.188c0.536,0.192,0.804,0.448,0.804,0.768c0,0.104-0.048,0.301-0.144,0.589l-2.304,6.659
|
||||
c-0.016,0.057-0.044,0.125-0.084,0.204c-0.04,0.08-0.146,0.187-0.318,0.318c-0.172,0.132-0.376,0.198-0.612,0.198
|
||||
c-0.236,0-0.44-0.066-0.612-0.198s-0.286-0.262-0.342-0.39l-1.404-4.141c-0.888,2.624-1.34,3.96-1.356,4.008
|
||||
c-0.016,0.049-0.052,0.116-0.108,0.204c-0.056,0.089-0.12,0.168-0.192,0.24c-0.184,0.185-0.404,0.276-0.66,0.276
|
||||
s-0.466-0.061-0.63-0.181c-0.164-0.119-0.274-0.239-0.33-0.359l-0.084-0.181l-2.316-6.659c-0.088-0.265-0.132-0.46-0.132-0.589
|
||||
c0-0.319,0.268-0.571,0.804-0.756c0.232-0.079,0.442-0.12,0.63-0.12s0.332,0.064,0.432,0.192s0.19,0.324,0.27,0.588l1.32,4.008
|
||||
l1.308-3.947c0.112-0.336,0.316-0.568,0.612-0.696c0.128-0.056,0.294-0.084,0.498-0.084c0.204,0,0.394,0.065,0.57,0.198
|
||||
c0.176,0.132,0.288,0.262,0.336,0.39l1.38,4.164l1.32-4.032c0.064-0.184,0.116-0.319,0.156-0.408
|
||||
c0.04-0.088,0.114-0.174,0.222-0.258s0.242-0.126,0.402-0.126S90.891,221.108,91.106,221.188z"/>
|
||||
<path class="st2" d="M95.895,227.812h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V227.812z"/>
|
||||
<path class="st2" d="M104.75,228.159h3.264c0.264,0,0.456,0.03,0.576,0.091c0.12,0.06,0.2,0.153,0.24,0.281s0.06,0.299,0.06,0.511
|
||||
s-0.02,0.382-0.06,0.51s-0.108,0.216-0.204,0.264c-0.152,0.08-0.36,0.12-0.624,0.12h-4.32c-0.56,0-0.888-0.152-0.984-0.456
|
||||
c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.184,0.006-0.321,0.018-0.414c0.012-0.092,0.05-0.197,0.114-0.317
|
||||
c0.112-0.217,0.424-0.324,0.936-0.324c0.56,0,0.892,0.148,0.996,0.444c0.04,0.136,0.06,0.344,0.06,0.624V228.159z"/>
|
||||
<path class="st2" d="M118.898,221.272c0.472,0.232,0.708,0.488,0.708,0.768c0,0.129-0.06,0.32-0.18,0.576l-3.312,6.721
|
||||
c-0.088,0.176-0.222,0.317-0.402,0.426c-0.18,0.107-0.366,0.162-0.558,0.162h-0.12c-0.2,0-0.39-0.055-0.57-0.162
|
||||
c-0.18-0.108-0.314-0.25-0.402-0.426l-3.312-6.721c-0.12-0.256-0.18-0.447-0.18-0.576c0-0.279,0.236-0.535,0.708-0.768
|
||||
c0.264-0.136,0.466-0.204,0.606-0.204c0.14,0,0.246,0.017,0.318,0.048c0.072,0.032,0.14,0.089,0.204,0.168
|
||||
c0.072,0.097,0.138,0.202,0.198,0.318s0.214,0.448,0.462,0.996s0.514,1.13,0.798,1.746c0.284,0.616,0.552,1.198,0.804,1.746
|
||||
s0.394,0.854,0.426,0.918l2.4-5.256c0.064-0.152,0.12-0.272,0.168-0.36c0.144-0.216,0.32-0.324,0.528-0.324
|
||||
S118.634,221.136,118.898,221.272z"/>
|
||||
<path class="st2" d="M123.59,227.812h3.696c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-4.752
|
||||
c-0.56,0-0.888-0.152-0.984-0.456c-0.048-0.128-0.072-0.332-0.072-0.612v-6.672c0-0.408,0.076-0.686,0.228-0.834
|
||||
c0.152-0.147,0.44-0.222,0.864-0.222h4.728c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114
|
||||
c0.216,0.112,0.324,0.424,0.324,0.937c0,0.56-0.148,0.888-0.444,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-3.684v1.212h2.376
|
||||
c0.184,0,0.322,0.006,0.414,0.018c0.092,0.013,0.198,0.051,0.318,0.114c0.216,0.112,0.324,0.424,0.324,0.937
|
||||
c0,0.56-0.152,0.888-0.456,0.983c-0.136,0.048-0.344,0.072-0.624,0.072h-2.352V227.812z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M131.993,13.583c-0.875-0.408-1.248-1.08-1.248-1.751c0-1.235,1.043-2.075,2.423-2.075c1.511,0,2.279,0.936,2.279,1.919
|
||||
c0,0.66-0.336,1.379-1.295,1.823v0.036c0.972,0.384,1.571,1.08,1.571,2.015c0,1.367-1.164,2.267-2.651,2.267
|
||||
c-1.631,0-2.614-0.959-2.614-2.099c0-0.983,0.587-1.691,1.547-2.099L131.993,13.583z M134.656,15.657
|
||||
c0-0.936-0.66-1.403-1.715-1.703c-0.911,0.264-1.403,0.875-1.403,1.619c-0.036,0.78,0.564,1.475,1.56,1.475
|
||||
C134.044,17.048,134.656,16.461,134.656,15.657z M131.753,11.759c-0.012,0.78,0.587,1.199,1.487,1.439
|
||||
c0.672-0.228,1.188-0.708,1.188-1.416c0-0.624-0.372-1.271-1.319-1.271C132.233,10.512,131.753,11.088,131.753,11.759z"/>
|
||||
<path d="M141.903,13.702c0,2.651-0.996,4.114-2.71,4.114c-1.523,0-2.567-1.427-2.591-4.006c0-2.626,1.14-4.054,2.723-4.054
|
||||
C140.955,9.756,141.903,11.22,141.903,13.702z M137.669,13.822c0,2.027,0.624,3.178,1.583,3.178c1.067,0,1.583-1.259,1.583-3.25
|
||||
c0-1.919-0.48-3.178-1.583-3.178C138.341,10.572,137.669,11.699,137.669,13.822z"/>
|
||||
<path d="M143.201,13.45c0-0.611-0.024-1.091-0.048-1.571h0.923l0.048,0.947h0.036c0.324-0.552,0.864-1.067,1.835-1.067
|
||||
c0.779,0,1.379,0.48,1.631,1.164h0.023c0.181-0.336,0.42-0.576,0.66-0.756c0.348-0.264,0.72-0.408,1.271-0.408
|
||||
c0.779,0,1.919,0.504,1.919,2.519v3.406h-1.032V14.41c0-1.127-0.419-1.787-1.259-1.787c-0.611,0-1.067,0.443-1.26,0.947
|
||||
c-0.048,0.156-0.084,0.336-0.084,0.528v3.586h-1.031v-3.478c0-0.923-0.407-1.583-1.211-1.583c-0.648,0-1.14,0.527-1.308,1.055
|
||||
c-0.06,0.144-0.084,0.336-0.084,0.516v3.49h-1.031V13.45z"/>
|
||||
<path d="M153.21,13.45c0-0.611-0.024-1.091-0.049-1.571h0.924l0.048,0.947h0.036c0.324-0.552,0.863-1.067,1.835-1.067
|
||||
c0.779,0,1.379,0.48,1.631,1.164h0.024c0.18-0.336,0.42-0.576,0.659-0.756c0.348-0.264,0.72-0.408,1.271-0.408
|
||||
c0.779,0,1.919,0.504,1.919,2.519v3.406h-1.031V14.41c0-1.127-0.42-1.787-1.26-1.787c-0.611,0-1.067,0.443-1.259,0.947
|
||||
c-0.048,0.156-0.084,0.336-0.084,0.528v3.586h-1.031v-3.478c0-0.923-0.408-1.583-1.212-1.583c-0.647,0-1.139,0.527-1.307,1.055
|
||||
c-0.061,0.144-0.084,0.336-0.084,0.516v3.49h-1.031V13.45z"/>
|
||||
</g>
|
||||
<line class="st3" x1="31.102" y1="20.469" x2="31.102" y2="9.225"/>
|
||||
<line class="st3" x1="257.874" y1="20.469" x2="257.874" y2="9.225"/>
|
||||
<line class="st3" x1="257.874" y1="14.847" x2="165.853" y2="14.847"/>
|
||||
<line class="st3" x1="123.888" y1="14.847" x2="31.102" y2="14.847"/>
|
||||
</svg>
|
After Width: | Height: | Size: 82 KiB |
305
usermods/word-clock-matrix/word-clock-matrix.cpp
Normal file
@@ -0,0 +1,305 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This v1 usermod file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
|
||||
*
|
||||
* Consider the v2 usermod API if you need a more advanced feature set!
|
||||
*/
|
||||
|
||||
|
||||
uint8_t minuteLast = 99;
|
||||
int dayBrightness = 128;
|
||||
int nightBrightness = 16;
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
saveMacro(14, "A=128", false);
|
||||
saveMacro(15, "A=64", false);
|
||||
saveMacro(16, "A=16", false);
|
||||
|
||||
saveMacro(1, "&FX=0&R=255&G=255&B=255", false);
|
||||
|
||||
//strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||
|
||||
//select first two segments (background color + FX settable)
|
||||
WS2812FX::Segment &seg = strip.getSegment(0);
|
||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((0 & 0xFF) << 8) | ((0 & 0xFF)));
|
||||
strip.getSegment(0).setOption(0, false);
|
||||
strip.getSegment(0).setOption(2, false);
|
||||
//other segments are text
|
||||
for (int i = 1; i < 10; i++)
|
||||
{
|
||||
WS2812FX::Segment &seg = strip.getSegment(i);
|
||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
||||
strip.getSegment(i).setOption(0, true);
|
||||
strip.setBrightness(128);
|
||||
}
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
}
|
||||
|
||||
void selectWordSegments(bool state)
|
||||
{
|
||||
for (int i = 1; i < 10; i++)
|
||||
{
|
||||
//WS2812FX::Segment &seg = strip.getSegment(i);
|
||||
strip.getSegment(i).setOption(0, state);
|
||||
// strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||
//seg.mode = 12;
|
||||
//seg.palette = 1;
|
||||
//strip.setBrightness(255);
|
||||
}
|
||||
strip.getSegment(0).setOption(0, !state);
|
||||
}
|
||||
|
||||
void hourChime()
|
||||
{
|
||||
//strip.resetSegments();
|
||||
selectWordSegments(true);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
savePreset(13, false);
|
||||
selectWordSegments(false);
|
||||
//strip.getSegment(0).setOption(0, true);
|
||||
strip.getSegment(0).setOption(2, true);
|
||||
applyPreset(12);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
}
|
||||
|
||||
void displayTime(byte hour, byte minute)
|
||||
{
|
||||
bool isToHour = false; //true if minute > 30
|
||||
strip.setSegment(0, 0, 64); // background
|
||||
strip.setSegment(1, 0, 2); //It is
|
||||
|
||||
strip.setSegment(2, 0, 0);
|
||||
strip.setSegment(3, 0, 0); //disable minutes
|
||||
strip.setSegment(4, 0, 0); //past
|
||||
strip.setSegment(6, 0, 0); //to
|
||||
strip.setSegment(8, 0, 0); //disable o'clock
|
||||
|
||||
if (hour < 24) //valid time, display
|
||||
{
|
||||
if (minute == 30)
|
||||
{
|
||||
strip.setSegment(2, 3, 6); //half
|
||||
strip.setSegment(3, 0, 0); //minutes
|
||||
}
|
||||
else if (minute == 15 || minute == 45)
|
||||
{
|
||||
strip.setSegment(3, 0, 0); //minutes
|
||||
}
|
||||
else if (minute == 10)
|
||||
{
|
||||
//strip.setSegment(5, 6, 8); //ten
|
||||
}
|
||||
else if (minute == 5)
|
||||
{
|
||||
//strip.setSegment(5, 16, 18); //five
|
||||
}
|
||||
else if (minute == 0)
|
||||
{
|
||||
strip.setSegment(3, 0, 0); //minutes
|
||||
//hourChime();
|
||||
}
|
||||
else
|
||||
{
|
||||
strip.setSegment(3, 18, 22); //minutes
|
||||
}
|
||||
|
||||
//past or to?
|
||||
if (minute == 0)
|
||||
{ //full hour
|
||||
strip.setSegment(3, 0, 0); //disable minutes
|
||||
strip.setSegment(4, 0, 0); //disable past
|
||||
strip.setSegment(6, 0, 0); //disable to
|
||||
strip.setSegment(8, 60, 64); //o'clock
|
||||
}
|
||||
else if (minute > 34)
|
||||
{
|
||||
//strip.setSegment(6, 22, 24); //to
|
||||
//minute = 60 - minute;
|
||||
isToHour = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//strip.setSegment(4, 24, 27); //past
|
||||
//isToHour = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //temperature display
|
||||
}
|
||||
|
||||
//byte minuteRem = minute %10;
|
||||
|
||||
if (minute <= 4)
|
||||
{
|
||||
strip.setSegment(3, 0, 0); //nothing
|
||||
strip.setSegment(5, 0, 0); //nothing
|
||||
strip.setSegment(6, 0, 0); //nothing
|
||||
strip.setSegment(8, 60, 64); //o'clock
|
||||
}
|
||||
else if (minute <= 9)
|
||||
{
|
||||
strip.setSegment(5, 16, 18); // five past
|
||||
strip.setSegment(4, 24, 27); //past
|
||||
}
|
||||
else if (minute <= 14)
|
||||
{
|
||||
strip.setSegment(5, 6, 8); // ten past
|
||||
strip.setSegment(4, 24, 27); //past
|
||||
}
|
||||
else if (minute <= 19)
|
||||
{
|
||||
strip.setSegment(5, 8, 12); // quarter past
|
||||
strip.setSegment(3, 0, 0); //minutes
|
||||
strip.setSegment(4, 24, 27); //past
|
||||
}
|
||||
else if (minute <= 24)
|
||||
{
|
||||
strip.setSegment(5, 12, 16); // twenty past
|
||||
strip.setSegment(4, 24, 27); //past
|
||||
}
|
||||
else if (minute <= 29)
|
||||
{
|
||||
strip.setSegment(5, 12, 18); // twenty-five past
|
||||
strip.setSegment(4, 24, 27); //past
|
||||
}
|
||||
else if (minute <= 34)
|
||||
{
|
||||
strip.setSegment(5, 3, 6); // half past
|
||||
strip.setSegment(3, 0, 0); //minutes
|
||||
strip.setSegment(4, 24, 27); //past
|
||||
}
|
||||
else if (minute <= 39)
|
||||
{
|
||||
strip.setSegment(5, 12, 18); // twenty-five to
|
||||
strip.setSegment(6, 22, 24); //to
|
||||
}
|
||||
else if (minute <= 44)
|
||||
{
|
||||
strip.setSegment(5, 12, 16); // twenty to
|
||||
strip.setSegment(6, 22, 24); //to
|
||||
}
|
||||
else if (minute <= 49)
|
||||
{
|
||||
strip.setSegment(5, 8, 12); // quarter to
|
||||
strip.setSegment(3, 0, 0); //minutes
|
||||
strip.setSegment(6, 22, 24); //to
|
||||
}
|
||||
else if (minute <= 54)
|
||||
{
|
||||
strip.setSegment(5, 6, 8); // ten to
|
||||
strip.setSegment(6, 22, 24); //to
|
||||
}
|
||||
else if (minute <= 59)
|
||||
{
|
||||
strip.setSegment(5, 16, 18); // five to
|
||||
strip.setSegment(6, 22, 24); //to
|
||||
}
|
||||
|
||||
//hours
|
||||
if (hour > 23)
|
||||
return;
|
||||
if (isToHour)
|
||||
hour++;
|
||||
if (hour > 12)
|
||||
hour -= 12;
|
||||
if (hour == 0)
|
||||
hour = 12;
|
||||
|
||||
switch (hour)
|
||||
{
|
||||
case 1:
|
||||
strip.setSegment(7, 27, 29);
|
||||
break; //one
|
||||
case 2:
|
||||
strip.setSegment(7, 35, 37);
|
||||
break; //two
|
||||
case 3:
|
||||
strip.setSegment(7, 29, 32);
|
||||
break; //three
|
||||
case 4:
|
||||
strip.setSegment(7, 32, 35);
|
||||
break; //four
|
||||
case 5:
|
||||
strip.setSegment(7, 37, 40);
|
||||
break; //five
|
||||
case 6:
|
||||
strip.setSegment(7, 43, 45);
|
||||
break; //six
|
||||
case 7:
|
||||
strip.setSegment(7, 40, 43);
|
||||
break; //seven
|
||||
case 8:
|
||||
strip.setSegment(7, 45, 48);
|
||||
break; //eight
|
||||
case 9:
|
||||
strip.setSegment(7, 48, 50);
|
||||
break; //nine
|
||||
case 10:
|
||||
strip.setSegment(7, 54, 56);
|
||||
break; //ten
|
||||
case 11:
|
||||
strip.setSegment(7, 50, 54);
|
||||
break; //eleven
|
||||
case 12:
|
||||
strip.setSegment(7, 56, 60);
|
||||
break; //twelve
|
||||
}
|
||||
|
||||
selectWordSegments(true);
|
||||
applyMacro(1);
|
||||
}
|
||||
|
||||
void timeOfDay() {
|
||||
// NOT USED: use timed macros instead
|
||||
//Used to set brightness dependant of time of day - lights dimmed at night
|
||||
|
||||
//monday to thursday and sunday
|
||||
|
||||
if ((weekday(localTime) == 6) | (weekday(localTime) == 7)) {
|
||||
if (hour(localTime) > 0 | hour(localTime) < 8) {
|
||||
strip.setBrightness(nightBrightness);
|
||||
}
|
||||
else {
|
||||
strip.setBrightness(dayBrightness);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hour(localTime) < 6 | hour(localTime) >= 22) {
|
||||
strip.setBrightness(nightBrightness);
|
||||
}
|
||||
else {
|
||||
strip.setBrightness(dayBrightness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
if (minute(localTime) != minuteLast)
|
||||
{
|
||||
updateLocalTime();
|
||||
//timeOfDay();
|
||||
minuteLast = minute(localTime);
|
||||
displayTime(hour(localTime), minute(localTime));
|
||||
if (minute(localTime) == 0){
|
||||
hourChime();
|
||||
}
|
||||
if (minute(localTime) == 1){
|
||||
//turn off background segment;
|
||||
strip.getSegment(0).setOption(2, false);
|
||||
//applyPreset(13);
|
||||
}
|
||||
}
|
||||
}
|
25
wled00.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28010.2046
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wled00", "wled00\wled00.vcxproj", "{C5F80730-F44F-4478-BDAE-6634EFC2CA88}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9A679C2B-61D3-400B-B96F-06E604E9CED2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
BIN
wled00/.vs/wled00/v15/.suo
Normal file
3714
wled00/FX.cpp
Normal file
723
wled00/FX.h
Normal file
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
WS2812FX.h - Library for WS2812 LED effects.
|
||||
Harm Aldick - 2016
|
||||
www.aldick.org
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Harm Aldick
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Modified for WLED
|
||||
*/
|
||||
|
||||
#ifndef WS2812FX_h
|
||||
#define WS2812FX_h
|
||||
|
||||
#include "NpbWrapper.h"
|
||||
#include "const.h"
|
||||
|
||||
#define FASTLED_INTERNAL //remove annoying pragma messages
|
||||
#define USE_GET_MILLISECOND_TIMER
|
||||
#include "FastLED.h"
|
||||
|
||||
#define DEFAULT_BRIGHTNESS (uint8_t)127
|
||||
#define DEFAULT_MODE (uint8_t)0
|
||||
#define DEFAULT_SPEED (uint8_t)128
|
||||
#define DEFAULT_COLOR (uint32_t)0xFFAA00
|
||||
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
/* Not used in all effects yet */
|
||||
#define WLED_FPS 42
|
||||
#define FRAMETIME (1000/WLED_FPS)
|
||||
|
||||
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
|
||||
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
|
||||
#define MAX_NUM_SEGMENTS 10
|
||||
|
||||
/* How much data bytes all segments combined may allocate */
|
||||
#ifdef ESP8266
|
||||
#define MAX_SEGMENT_DATA 2048
|
||||
#else
|
||||
#define MAX_SEGMENT_DATA 8192
|
||||
#endif
|
||||
|
||||
#define LED_SKIP_AMOUNT 1
|
||||
#define MIN_SHOW_DELAY 15
|
||||
|
||||
#define NUM_COLORS 3 /* number of colors per segment */
|
||||
#define SEGMENT _segments[_segment_index]
|
||||
#define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x])
|
||||
#define SEGENV _segment_runtimes[_segment_index]
|
||||
#define SEGLEN _virtualSegmentLength
|
||||
#define SEGACT SEGMENT.stop
|
||||
#define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGLEN
|
||||
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
|
||||
|
||||
// some common colors
|
||||
#define RED (uint32_t)0xFF0000
|
||||
#define GREEN (uint32_t)0x00FF00
|
||||
#define BLUE (uint32_t)0x0000FF
|
||||
#define WHITE (uint32_t)0xFFFFFF
|
||||
#define BLACK (uint32_t)0x000000
|
||||
#define YELLOW (uint32_t)0xFFFF00
|
||||
#define CYAN (uint32_t)0x00FFFF
|
||||
#define MAGENTA (uint32_t)0xFF00FF
|
||||
#define PURPLE (uint32_t)0x400080
|
||||
#define ORANGE (uint32_t)0xFF3000
|
||||
#define PINK (uint32_t)0xFF1493
|
||||
#define ULTRAWHITE (uint32_t)0xFFFFFFFF
|
||||
|
||||
// options
|
||||
// bit 7: segment is in transition mode
|
||||
// bits 4-6: TBD
|
||||
// bit 3: mirror effect within segment
|
||||
// bit 2: segment is on
|
||||
// bit 1: reverse segment
|
||||
// bit 0: segment is selected
|
||||
#define NO_OPTIONS (uint8_t)0x00
|
||||
#define TRANSITIONAL (uint8_t)0x80
|
||||
#define MIRROR (uint8_t)0x08
|
||||
#define SEGMENT_ON (uint8_t)0x04
|
||||
#define REVERSE (uint8_t)0x02
|
||||
#define SELECTED (uint8_t)0x01
|
||||
#define IS_TRANSITIONAL ((SEGMENT.options & TRANSITIONAL) == TRANSITIONAL)
|
||||
#define IS_MIRROR ((SEGMENT.options & MIRROR ) == MIRROR )
|
||||
#define IS_SEGMENT_ON ((SEGMENT.options & SEGMENT_ON ) == SEGMENT_ON )
|
||||
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
|
||||
#define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED )
|
||||
|
||||
#define MODE_COUNT 113
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
#define FX_MODE_BREATH 2
|
||||
#define FX_MODE_COLOR_WIPE 3
|
||||
#define FX_MODE_COLOR_WIPE_RANDOM 4
|
||||
#define FX_MODE_RANDOM_COLOR 5
|
||||
#define FX_MODE_COLOR_SWEEP 6
|
||||
#define FX_MODE_DYNAMIC 7
|
||||
#define FX_MODE_RAINBOW 8
|
||||
#define FX_MODE_RAINBOW_CYCLE 9
|
||||
#define FX_MODE_SCAN 10
|
||||
#define FX_MODE_DUAL_SCAN 11
|
||||
#define FX_MODE_FADE 12
|
||||
#define FX_MODE_THEATER_CHASE 13
|
||||
#define FX_MODE_THEATER_CHASE_RAINBOW 14
|
||||
#define FX_MODE_RUNNING_LIGHTS 15
|
||||
#define FX_MODE_SAW 16
|
||||
#define FX_MODE_TWINKLE 17
|
||||
#define FX_MODE_DISSOLVE 18
|
||||
#define FX_MODE_DISSOLVE_RANDOM 19
|
||||
#define FX_MODE_SPARKLE 20
|
||||
#define FX_MODE_FLASH_SPARKLE 21
|
||||
#define FX_MODE_HYPER_SPARKLE 22
|
||||
#define FX_MODE_STROBE 23
|
||||
#define FX_MODE_STROBE_RAINBOW 24
|
||||
#define FX_MODE_MULTI_STROBE 25
|
||||
#define FX_MODE_BLINK_RAINBOW 26
|
||||
#define FX_MODE_ANDROID 27
|
||||
#define FX_MODE_CHASE_COLOR 28
|
||||
#define FX_MODE_CHASE_RANDOM 29
|
||||
#define FX_MODE_CHASE_RAINBOW 30
|
||||
#define FX_MODE_CHASE_FLASH 31
|
||||
#define FX_MODE_CHASE_FLASH_RANDOM 32
|
||||
#define FX_MODE_CHASE_RAINBOW_WHITE 33
|
||||
#define FX_MODE_COLORFUL 34
|
||||
#define FX_MODE_TRAFFIC_LIGHT 35
|
||||
#define FX_MODE_COLOR_SWEEP_RANDOM 36
|
||||
#define FX_MODE_RUNNING_COLOR 37
|
||||
#define FX_MODE_RUNNING_RED_BLUE 38
|
||||
#define FX_MODE_RUNNING_RANDOM 39
|
||||
#define FX_MODE_LARSON_SCANNER 40
|
||||
#define FX_MODE_COMET 41
|
||||
#define FX_MODE_FIREWORKS 42
|
||||
#define FX_MODE_RAIN 43
|
||||
#define FX_MODE_MERRY_CHRISTMAS 44
|
||||
#define FX_MODE_FIRE_FLICKER 45
|
||||
#define FX_MODE_GRADIENT 46
|
||||
#define FX_MODE_LOADING 47
|
||||
#define FX_MODE_POLICE 48
|
||||
#define FX_MODE_POLICE_ALL 49
|
||||
#define FX_MODE_TWO_DOTS 50
|
||||
#define FX_MODE_TWO_AREAS 51
|
||||
#define FX_MODE_CIRCUS_COMBUSTUS 52
|
||||
#define FX_MODE_HALLOWEEN 53
|
||||
#define FX_MODE_TRICOLOR_CHASE 54
|
||||
#define FX_MODE_TRICOLOR_WIPE 55
|
||||
#define FX_MODE_TRICOLOR_FADE 56
|
||||
#define FX_MODE_LIGHTNING 57
|
||||
#define FX_MODE_ICU 58
|
||||
#define FX_MODE_MULTI_COMET 59
|
||||
#define FX_MODE_DUAL_LARSON_SCANNER 60
|
||||
#define FX_MODE_RANDOM_CHASE 61
|
||||
#define FX_MODE_OSCILLATE 62
|
||||
#define FX_MODE_PRIDE_2015 63
|
||||
#define FX_MODE_JUGGLE 64
|
||||
#define FX_MODE_PALETTE 65
|
||||
#define FX_MODE_FIRE_2012 66
|
||||
#define FX_MODE_COLORWAVES 67
|
||||
#define FX_MODE_BPM 68
|
||||
#define FX_MODE_FILLNOISE8 69
|
||||
#define FX_MODE_NOISE16_1 70
|
||||
#define FX_MODE_NOISE16_2 71
|
||||
#define FX_MODE_NOISE16_3 72
|
||||
#define FX_MODE_NOISE16_4 73
|
||||
#define FX_MODE_COLORTWINKLE 74
|
||||
#define FX_MODE_LAKE 75
|
||||
#define FX_MODE_METEOR 76
|
||||
#define FX_MODE_METEOR_SMOOTH 77
|
||||
#define FX_MODE_RAILWAY 78
|
||||
#define FX_MODE_RIPPLE 79
|
||||
#define FX_MODE_TWINKLEFOX 80
|
||||
#define FX_MODE_TWINKLECAT 81
|
||||
#define FX_MODE_HALLOWEEN_EYES 82
|
||||
#define FX_MODE_STATIC_PATTERN 83
|
||||
#define FX_MODE_TRI_STATIC_PATTERN 84
|
||||
#define FX_MODE_SPOTS 85
|
||||
#define FX_MODE_SPOTS_FADE 86
|
||||
#define FX_MODE_GLITTER 87
|
||||
#define FX_MODE_CANDLE 88
|
||||
#define FX_MODE_STARBURST 89
|
||||
#define FX_MODE_EXPLODING_FIREWORKS 90
|
||||
#define FX_MODE_BOUNCINGBALLS 91
|
||||
#define FX_MODE_SINELON 92
|
||||
#define FX_MODE_SINELON_DUAL 93
|
||||
#define FX_MODE_SINELON_RAINBOW 94
|
||||
#define FX_MODE_POPCORN 95
|
||||
#define FX_MODE_DRIP 96
|
||||
#define FX_MODE_PLASMA 97
|
||||
#define FX_MODE_PERCENT 98
|
||||
#define FX_MODE_RIPPLE_RAINBOW 99
|
||||
#define FX_MODE_HEARTBEAT 100
|
||||
#define FX_MODE_PACIFICA 101
|
||||
#define FX_MODE_CANDLE_MULTI 102
|
||||
#define FX_MODE_SOLID_GLITTER 103
|
||||
#define FX_MODE_SUNRISE 104
|
||||
#define FX_MODE_PHASED 105
|
||||
#define FX_MODE_TWINKLEUP 106
|
||||
#define FX_MODE_NOISEPAL 107
|
||||
#define FX_MODE_SINEWAVE 108
|
||||
#define FX_MODE_PHASEDNOISE 109
|
||||
#define FX_MODE_FLOW 110
|
||||
#define FX_MODE_CHUNCHUN 111
|
||||
#define FX_MODE_DANCING_SHADOWS 112
|
||||
|
||||
class WS2812FX {
|
||||
typedef uint16_t (WS2812FX::*mode_ptr)(void);
|
||||
|
||||
// pre show callback
|
||||
typedef void (*show_callback) (void);
|
||||
|
||||
// segment parameters
|
||||
public:
|
||||
typedef struct Segment { // 24 bytes
|
||||
uint16_t start;
|
||||
uint16_t stop; //segment invalid if stop == 0
|
||||
uint8_t speed;
|
||||
uint8_t intensity;
|
||||
uint8_t palette;
|
||||
uint8_t mode;
|
||||
uint8_t options; //bit pattern: msb first: transitional needspixelstate tbd tbd (paused) on reverse selected
|
||||
uint8_t grouping, spacing;
|
||||
uint8_t opacity;
|
||||
uint32_t colors[NUM_COLORS];
|
||||
void setOption(uint8_t n, bool val)
|
||||
{
|
||||
if (val) {
|
||||
options |= 0x01 << n;
|
||||
} else
|
||||
{
|
||||
options &= ~(0x01 << n);
|
||||
}
|
||||
}
|
||||
bool getOption(uint8_t n)
|
||||
{
|
||||
return ((options >> n) & 0x01);
|
||||
}
|
||||
bool isSelected()
|
||||
{
|
||||
return getOption(0);
|
||||
}
|
||||
bool isActive()
|
||||
{
|
||||
return stop > start;
|
||||
}
|
||||
uint16_t length()
|
||||
{
|
||||
return stop - start;
|
||||
}
|
||||
uint16_t groupLength()
|
||||
{
|
||||
return grouping + spacing;
|
||||
}
|
||||
uint16_t virtualLength()
|
||||
{
|
||||
uint16_t groupLen = groupLength();
|
||||
uint16_t vLength = (length() + groupLen - 1) / groupLen;
|
||||
if (options & MIRROR)
|
||||
vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
return vLength;
|
||||
}
|
||||
} segment;
|
||||
|
||||
// segment runtime parameters
|
||||
typedef struct Segment_runtime { // 28 bytes
|
||||
unsigned long next_time;
|
||||
uint32_t step;
|
||||
uint32_t call;
|
||||
uint16_t aux0;
|
||||
uint16_t aux1;
|
||||
byte* data = nullptr;
|
||||
bool allocateData(uint16_t len){
|
||||
if (data && _dataLen == len) return true; //already allocated
|
||||
deallocateData();
|
||||
if (WS2812FX::_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||
data = new (std::nothrow) byte[len];
|
||||
if (!data) return false; //allocation failed
|
||||
WS2812FX::_usedSegmentData += len;
|
||||
_dataLen = len;
|
||||
memset(data, 0, len);
|
||||
return true;
|
||||
}
|
||||
void deallocateData(){
|
||||
delete[] data;
|
||||
data = nullptr;
|
||||
WS2812FX::_usedSegmentData -= _dataLen;
|
||||
_dataLen = 0;
|
||||
}
|
||||
void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();}
|
||||
private:
|
||||
uint16_t _dataLen = 0;
|
||||
} segment_runtime;
|
||||
|
||||
WS2812FX() {
|
||||
//assign each member of the _mode[] array to its respective function reference
|
||||
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
|
||||
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
|
||||
_mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe;
|
||||
_mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random;
|
||||
_mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color;
|
||||
_mode[FX_MODE_COLOR_SWEEP] = &WS2812FX::mode_color_sweep;
|
||||
_mode[FX_MODE_DYNAMIC] = &WS2812FX::mode_dynamic;
|
||||
_mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow;
|
||||
_mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle;
|
||||
_mode[FX_MODE_SCAN] = &WS2812FX::mode_scan;
|
||||
_mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan;
|
||||
_mode[FX_MODE_FADE] = &WS2812FX::mode_fade;
|
||||
_mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase;
|
||||
_mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow;
|
||||
_mode[FX_MODE_SAW] = &WS2812FX::mode_saw;
|
||||
_mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle;
|
||||
_mode[FX_MODE_DISSOLVE] = &WS2812FX::mode_dissolve;
|
||||
_mode[FX_MODE_DISSOLVE_RANDOM] = &WS2812FX::mode_dissolve_random;
|
||||
_mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle;
|
||||
_mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle;
|
||||
_mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle;
|
||||
_mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe;
|
||||
_mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow;
|
||||
_mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe;
|
||||
_mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow;
|
||||
_mode[FX_MODE_ANDROID] = &WS2812FX::mode_android;
|
||||
_mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color;
|
||||
_mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random;
|
||||
_mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow;
|
||||
_mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash;
|
||||
_mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random;
|
||||
_mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white;
|
||||
_mode[FX_MODE_COLORFUL] = &WS2812FX::mode_colorful;
|
||||
_mode[FX_MODE_TRAFFIC_LIGHT] = &WS2812FX::mode_traffic_light;
|
||||
_mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random;
|
||||
_mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color;
|
||||
_mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue;
|
||||
_mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random;
|
||||
_mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner;
|
||||
_mode[FX_MODE_COMET] = &WS2812FX::mode_comet;
|
||||
_mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks;
|
||||
_mode[FX_MODE_RAIN] = &WS2812FX::mode_rain;
|
||||
_mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas;
|
||||
_mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker;
|
||||
_mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient;
|
||||
_mode[FX_MODE_LOADING] = &WS2812FX::mode_loading;
|
||||
_mode[FX_MODE_POLICE] = &WS2812FX::mode_police;
|
||||
_mode[FX_MODE_POLICE_ALL] = &WS2812FX::mode_police_all;
|
||||
_mode[FX_MODE_TWO_DOTS] = &WS2812FX::mode_two_dots;
|
||||
_mode[FX_MODE_TWO_AREAS] = &WS2812FX::mode_two_areas;
|
||||
_mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus;
|
||||
_mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween;
|
||||
_mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase;
|
||||
_mode[FX_MODE_TRICOLOR_WIPE] = &WS2812FX::mode_tricolor_wipe;
|
||||
_mode[FX_MODE_TRICOLOR_FADE] = &WS2812FX::mode_tricolor_fade;
|
||||
_mode[FX_MODE_BREATH] = &WS2812FX::mode_breath;
|
||||
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights;
|
||||
_mode[FX_MODE_LIGHTNING] = &WS2812FX::mode_lightning;
|
||||
_mode[FX_MODE_ICU] = &WS2812FX::mode_icu;
|
||||
_mode[FX_MODE_MULTI_COMET] = &WS2812FX::mode_multi_comet;
|
||||
_mode[FX_MODE_DUAL_LARSON_SCANNER] = &WS2812FX::mode_dual_larson_scanner;
|
||||
_mode[FX_MODE_RANDOM_CHASE] = &WS2812FX::mode_random_chase;
|
||||
_mode[FX_MODE_OSCILLATE] = &WS2812FX::mode_oscillate;
|
||||
_mode[FX_MODE_FIRE_2012] = &WS2812FX::mode_fire_2012;
|
||||
_mode[FX_MODE_PRIDE_2015] = &WS2812FX::mode_pride_2015;
|
||||
_mode[FX_MODE_BPM] = &WS2812FX::mode_bpm;
|
||||
_mode[FX_MODE_JUGGLE] = &WS2812FX::mode_juggle;
|
||||
_mode[FX_MODE_PALETTE] = &WS2812FX::mode_palette;
|
||||
_mode[FX_MODE_COLORWAVES] = &WS2812FX::mode_colorwaves;
|
||||
_mode[FX_MODE_FILLNOISE8] = &WS2812FX::mode_fillnoise8;
|
||||
_mode[FX_MODE_NOISE16_1] = &WS2812FX::mode_noise16_1;
|
||||
_mode[FX_MODE_NOISE16_2] = &WS2812FX::mode_noise16_2;
|
||||
_mode[FX_MODE_NOISE16_3] = &WS2812FX::mode_noise16_3;
|
||||
_mode[FX_MODE_NOISE16_4] = &WS2812FX::mode_noise16_4;
|
||||
_mode[FX_MODE_COLORTWINKLE] = &WS2812FX::mode_colortwinkle;
|
||||
_mode[FX_MODE_LAKE] = &WS2812FX::mode_lake;
|
||||
_mode[FX_MODE_METEOR] = &WS2812FX::mode_meteor;
|
||||
_mode[FX_MODE_METEOR_SMOOTH] = &WS2812FX::mode_meteor_smooth;
|
||||
_mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway;
|
||||
_mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple;
|
||||
_mode[FX_MODE_TWINKLEFOX] = &WS2812FX::mode_twinklefox;
|
||||
_mode[FX_MODE_TWINKLECAT] = &WS2812FX::mode_twinklecat;
|
||||
_mode[FX_MODE_HALLOWEEN_EYES] = &WS2812FX::mode_halloween_eyes;
|
||||
_mode[FX_MODE_STATIC_PATTERN] = &WS2812FX::mode_static_pattern;
|
||||
_mode[FX_MODE_TRI_STATIC_PATTERN] = &WS2812FX::mode_tri_static_pattern;
|
||||
_mode[FX_MODE_SPOTS] = &WS2812FX::mode_spots;
|
||||
_mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade;
|
||||
_mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter;
|
||||
_mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle;
|
||||
_mode[FX_MODE_STARBURST] = &WS2812FX::mode_starburst;
|
||||
_mode[FX_MODE_EXPLODING_FIREWORKS] = &WS2812FX::mode_exploding_fireworks;
|
||||
_mode[FX_MODE_BOUNCINGBALLS] = &WS2812FX::mode_bouncing_balls;
|
||||
_mode[FX_MODE_SINELON] = &WS2812FX::mode_sinelon;
|
||||
_mode[FX_MODE_SINELON_DUAL] = &WS2812FX::mode_sinelon_dual;
|
||||
_mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow;
|
||||
_mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn;
|
||||
_mode[FX_MODE_DRIP] = &WS2812FX::mode_drip;
|
||||
_mode[FX_MODE_PLASMA] = &WS2812FX::mode_plasma;
|
||||
_mode[FX_MODE_PERCENT] = &WS2812FX::mode_percent;
|
||||
_mode[FX_MODE_RIPPLE_RAINBOW] = &WS2812FX::mode_ripple_rainbow;
|
||||
_mode[FX_MODE_HEARTBEAT] = &WS2812FX::mode_heartbeat;
|
||||
_mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica;
|
||||
_mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi;
|
||||
_mode[FX_MODE_SOLID_GLITTER] = &WS2812FX::mode_solid_glitter;
|
||||
_mode[FX_MODE_SUNRISE] = &WS2812FX::mode_sunrise;
|
||||
_mode[FX_MODE_PHASED] = &WS2812FX::mode_phased;
|
||||
_mode[FX_MODE_TWINKLEUP] = &WS2812FX::mode_twinkleup;
|
||||
_mode[FX_MODE_NOISEPAL] = &WS2812FX::mode_noisepal;
|
||||
_mode[FX_MODE_SINEWAVE] = &WS2812FX::mode_sinewave;
|
||||
_mode[FX_MODE_PHASEDNOISE] = &WS2812FX::mode_phased_noise;
|
||||
_mode[FX_MODE_FLOW] = &WS2812FX::mode_flow;
|
||||
_mode[FX_MODE_CHUNCHUN] = &WS2812FX::mode_chunchun;
|
||||
_mode[FX_MODE_DANCING_SHADOWS] = &WS2812FX::mode_dancing_shadows;
|
||||
|
||||
_brightness = DEFAULT_BRIGHTNESS;
|
||||
currentPalette = CRGBPalette16(CRGB::Black);
|
||||
targetPalette = CloudColors_p;
|
||||
ablMilliampsMax = 850;
|
||||
currentMilliamps = 0;
|
||||
timebase = 0;
|
||||
bus = new NeoPixelWrapper();
|
||||
resetSegments();
|
||||
}
|
||||
|
||||
void
|
||||
init(bool supportWhite, uint16_t countPixels, bool skipFirst),
|
||||
service(void),
|
||||
blur(uint8_t),
|
||||
fill(uint32_t),
|
||||
fade_out(uint8_t r),
|
||||
setMode(uint8_t segid, uint8_t m),
|
||||
setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
setColor(uint8_t slot, uint32_t c),
|
||||
setBrightness(uint8_t b),
|
||||
setRange(uint16_t i, uint16_t i2, uint32_t col),
|
||||
setShowCallback(show_callback cb),
|
||||
setTransitionMode(bool t),
|
||||
trigger(void),
|
||||
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0),
|
||||
resetSegments(),
|
||||
setPixelColor(uint16_t n, uint32_t c),
|
||||
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
show(void),
|
||||
setRgbwPwm(void),
|
||||
setPixelSegment(uint8_t n);
|
||||
|
||||
bool
|
||||
reverseMode = false, //is the entire LED strip reversed?
|
||||
gammaCorrectBri = false,
|
||||
gammaCorrectCol = true,
|
||||
applyToAllSelected = true,
|
||||
segmentsAreIdentical(Segment* a, Segment* b),
|
||||
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p);
|
||||
|
||||
uint8_t
|
||||
mainSegment = 0,
|
||||
rgbwMode = RGBW_MODE_DUAL,
|
||||
paletteFade = 0,
|
||||
paletteBlend = 0,
|
||||
colorOrder = 0,
|
||||
milliampsPerLed = 55,
|
||||
getBrightness(void),
|
||||
getMode(void),
|
||||
getSpeed(void),
|
||||
getModeCount(void),
|
||||
getPaletteCount(void),
|
||||
getMaxSegments(void),
|
||||
//getFirstSelectedSegment(void),
|
||||
getMainSegmentId(void),
|
||||
gamma8(uint8_t),
|
||||
get_random_wheel_index(uint8_t);
|
||||
|
||||
uint16_t
|
||||
ablMilliampsMax,
|
||||
currentMilliamps,
|
||||
triwave16(uint16_t);
|
||||
|
||||
uint32_t
|
||||
now,
|
||||
timebase,
|
||||
color_wheel(uint8_t),
|
||||
color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255),
|
||||
color_blend(uint32_t,uint32_t,uint8_t),
|
||||
gamma32(uint32_t),
|
||||
getLastShow(void),
|
||||
getPixelColor(uint16_t),
|
||||
getColor(void);
|
||||
|
||||
WS2812FX::Segment&
|
||||
getSegment(uint8_t n);
|
||||
|
||||
WS2812FX::Segment_runtime
|
||||
getSegmentRuntime(void);
|
||||
|
||||
WS2812FX::Segment*
|
||||
getSegments(void);
|
||||
|
||||
// builtin modes
|
||||
uint16_t
|
||||
mode_static(void),
|
||||
mode_blink(void),
|
||||
mode_blink_rainbow(void),
|
||||
mode_strobe(void),
|
||||
mode_strobe_rainbow(void),
|
||||
mode_color_wipe(void),
|
||||
mode_color_sweep(void),
|
||||
mode_color_wipe_random(void),
|
||||
mode_color_sweep_random(void),
|
||||
mode_random_color(void),
|
||||
mode_dynamic(void),
|
||||
mode_breath(void),
|
||||
mode_fade(void),
|
||||
mode_scan(void),
|
||||
mode_dual_scan(void),
|
||||
mode_theater_chase(void),
|
||||
mode_theater_chase_rainbow(void),
|
||||
mode_rainbow(void),
|
||||
mode_rainbow_cycle(void),
|
||||
mode_running_lights(void),
|
||||
mode_saw(void),
|
||||
mode_twinkle(void),
|
||||
mode_dissolve(void),
|
||||
mode_dissolve_random(void),
|
||||
mode_sparkle(void),
|
||||
mode_flash_sparkle(void),
|
||||
mode_hyper_sparkle(void),
|
||||
mode_multi_strobe(void),
|
||||
mode_android(void),
|
||||
mode_chase_color(void),
|
||||
mode_chase_random(void),
|
||||
mode_chase_rainbow(void),
|
||||
mode_chase_flash(void),
|
||||
mode_chase_flash_random(void),
|
||||
mode_chase_rainbow_white(void),
|
||||
mode_colorful(void),
|
||||
mode_traffic_light(void),
|
||||
mode_running_color(void),
|
||||
mode_running_red_blue(void),
|
||||
mode_running_random(void),
|
||||
mode_larson_scanner(void),
|
||||
mode_comet(void),
|
||||
mode_fireworks(void),
|
||||
mode_rain(void),
|
||||
mode_merry_christmas(void),
|
||||
mode_halloween(void),
|
||||
mode_fire_flicker(void),
|
||||
mode_gradient(void),
|
||||
mode_loading(void),
|
||||
mode_police(void),
|
||||
mode_police_all(void),
|
||||
mode_two_dots(void),
|
||||
mode_two_areas(void),
|
||||
mode_circus_combustus(void),
|
||||
mode_bicolor_chase(void),
|
||||
mode_tricolor_chase(void),
|
||||
mode_tricolor_wipe(void),
|
||||
mode_tricolor_fade(void),
|
||||
mode_lightning(void),
|
||||
mode_icu(void),
|
||||
mode_multi_comet(void),
|
||||
mode_dual_larson_scanner(void),
|
||||
mode_random_chase(void),
|
||||
mode_oscillate(void),
|
||||
mode_fire_2012(void),
|
||||
mode_pride_2015(void),
|
||||
mode_bpm(void),
|
||||
mode_juggle(void),
|
||||
mode_palette(void),
|
||||
mode_colorwaves(void),
|
||||
mode_fillnoise8(void),
|
||||
mode_noise16_1(void),
|
||||
mode_noise16_2(void),
|
||||
mode_noise16_3(void),
|
||||
mode_noise16_4(void),
|
||||
mode_colortwinkle(void),
|
||||
mode_lake(void),
|
||||
mode_meteor(void),
|
||||
mode_meteor_smooth(void),
|
||||
mode_railway(void),
|
||||
mode_ripple(void),
|
||||
mode_twinklefox(void),
|
||||
mode_twinklecat(void),
|
||||
mode_halloween_eyes(void),
|
||||
mode_static_pattern(void),
|
||||
mode_tri_static_pattern(void),
|
||||
mode_spots(void),
|
||||
mode_spots_fade(void),
|
||||
mode_glitter(void),
|
||||
mode_candle(void),
|
||||
mode_starburst(void),
|
||||
mode_exploding_fireworks(void),
|
||||
mode_bouncing_balls(void),
|
||||
mode_sinelon(void),
|
||||
mode_sinelon_dual(void),
|
||||
mode_sinelon_rainbow(void),
|
||||
mode_popcorn(void),
|
||||
mode_drip(void),
|
||||
mode_plasma(void),
|
||||
mode_percent(void),
|
||||
mode_ripple_rainbow(void),
|
||||
mode_heartbeat(void),
|
||||
mode_pacifica(void),
|
||||
mode_candle_multi(void),
|
||||
mode_solid_glitter(void),
|
||||
mode_sunrise(void),
|
||||
mode_phased(void),
|
||||
mode_twinkleup(void),
|
||||
mode_noisepal(void),
|
||||
mode_sinewave(void),
|
||||
mode_phased_noise(void),
|
||||
mode_flow(void),
|
||||
mode_chunchun(void),
|
||||
mode_dancing_shadows(void);
|
||||
|
||||
private:
|
||||
NeoPixelWrapper *bus;
|
||||
|
||||
uint32_t crgb_to_col(CRGB fastled);
|
||||
CRGB col_to_crgb(uint32_t);
|
||||
CRGBPalette16 currentPalette;
|
||||
CRGBPalette16 targetPalette;
|
||||
|
||||
uint16_t _length, _lengthRaw, _virtualSegmentLength;
|
||||
uint16_t _rand16seed;
|
||||
uint8_t _brightness;
|
||||
static uint16_t _usedSegmentData;
|
||||
|
||||
void load_gradient_palette(uint8_t);
|
||||
void handle_palette(void);
|
||||
|
||||
bool
|
||||
_useRgbw = false,
|
||||
_skipFirstMode,
|
||||
_triggered;
|
||||
|
||||
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
|
||||
|
||||
show_callback _callback = nullptr;
|
||||
|
||||
// mode helper functions
|
||||
uint16_t
|
||||
blink(uint32_t, uint32_t, bool strobe, bool),
|
||||
candle(bool),
|
||||
color_wipe(bool, bool),
|
||||
scan(bool),
|
||||
theater_chase(uint32_t, uint32_t, bool),
|
||||
running_base(bool),
|
||||
larson_scanner(bool),
|
||||
sinelon_base(bool,bool),
|
||||
dissolve(uint32_t),
|
||||
chase(uint32_t, uint32_t, uint32_t, bool),
|
||||
gradient_base(bool),
|
||||
ripple_base(bool),
|
||||
police_base(uint32_t, uint32_t, bool),
|
||||
running(uint32_t, uint32_t),
|
||||
tricolor_chase(uint32_t, uint32_t),
|
||||
twinklefox_base(bool),
|
||||
spots_base(uint16_t),
|
||||
phased_base(uint8_t);
|
||||
|
||||
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
|
||||
CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff);
|
||||
|
||||
void blendPixelColor(uint16_t n, uint32_t color, uint8_t blend);
|
||||
|
||||
uint32_t _lastPaletteChange = 0;
|
||||
uint32_t _lastShow = 0;
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
uint32_t _analogLastShow = 0;
|
||||
RgbwColor _analogLastColor = 0;
|
||||
uint8_t _analogLastBri = 0;
|
||||
#endif
|
||||
|
||||
uint8_t _segment_index = 0;
|
||||
uint8_t _segment_index_palette_last = 99;
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element
|
||||
// start, stop, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[]
|
||||
{ 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}}
|
||||
};
|
||||
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
|
||||
friend class Segment_runtime;
|
||||
|
||||
uint16_t realPixelIndex(uint16_t i);
|
||||
};
|
||||
|
||||
//10 names per line
|
||||
const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Solid","Blink","Breathe","Wipe","Wipe Random","Random Colors","Sweep","Dynamic","Colorloop","Rainbow",
|
||||
"Scan","Scan Dual","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd",
|
||||
"Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random",
|
||||
"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream",
|
||||
"Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","Police","Police All",
|
||||
"Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet",
|
||||
"Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise",
|
||||
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
|
||||
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",
|
||||
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow",
|
||||
"Heartbeat","Pacifica","Candle Multi", "Solid Glitter","Sunrise","Phased","Twinkleup","Noise Pal", "Sine","Phased Noise",
|
||||
"Flow","Chunchun","Dancing Shadows"
|
||||
])=====";
|
||||
|
||||
|
||||
const char JSON_palette_names[] PROGMEM = R"=====([
|
||||
"Default","* Random Cycle","* Color 1","* Colors 1&2","* Color Gradient","* Colors Only","Party","Cloud","Lava","Ocean",
|
||||
"Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash",
|
||||
"Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64",
|
||||
"Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn",
|
||||
"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura",
|
||||
"Aurora","Atlantica"
|
||||
])=====";
|
||||
|
||||
#endif
|
965
wled00/FX_fcn.cpp
Normal file
@@ -0,0 +1,965 @@
|
||||
/*
|
||||
WS2812FX_fcn.cpp contains all utility functions
|
||||
Harm Aldick - 2016
|
||||
www.aldick.org
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Harm Aldick
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Modified heavily for WLED
|
||||
*/
|
||||
|
||||
#include "FX.h"
|
||||
#include "palettes.h"
|
||||
|
||||
//enable custom per-LED mapping. This can allow for better effects on matrices or special displays
|
||||
//#define WLED_CUSTOM_LED_MAPPING
|
||||
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
//this is just an example (30 LEDs). It will first set all even, then all uneven LEDs.
|
||||
const uint16_t customMappingTable[] = {
|
||||
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
|
||||
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29};
|
||||
|
||||
//another example. Switches direction every 5 LEDs.
|
||||
/*const uint16_t customMappingTable[] = {
|
||||
0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14,
|
||||
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25};*/
|
||||
|
||||
const uint16_t customMappingSize = sizeof(customMappingTable)/sizeof(uint16_t); //30 in example
|
||||
#endif
|
||||
|
||||
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
|
||||
{
|
||||
if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return;
|
||||
RESET_RUNTIME;
|
||||
_useRgbw = supportWhite;
|
||||
_length = countPixels;
|
||||
_skipFirstMode = skipFirst;
|
||||
|
||||
uint8_t ty = 1;
|
||||
if (supportWhite) ty = 2;
|
||||
_lengthRaw = _length;
|
||||
if (_skipFirstMode) {
|
||||
_lengthRaw += LED_SKIP_AMOUNT;
|
||||
}
|
||||
|
||||
bus->Begin((NeoPixelType)ty, _lengthRaw);
|
||||
|
||||
_segments[0].start = 0;
|
||||
_segments[0].stop = _length;
|
||||
|
||||
setBrightness(_brightness);
|
||||
}
|
||||
|
||||
void WS2812FX::service() {
|
||||
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
|
||||
now = nowUp + timebase;
|
||||
if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
|
||||
bool doShow = false;
|
||||
|
||||
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segment_index = i;
|
||||
if (SEGMENT.isActive())
|
||||
{
|
||||
if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
|
||||
{
|
||||
if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check
|
||||
doShow = true;
|
||||
uint16_t delay = FRAMETIME;
|
||||
|
||||
if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
|
||||
_virtualSegmentLength = SEGMENT.virtualLength();
|
||||
handle_palette();
|
||||
delay = (this->*_mode[SEGMENT.mode])(); //effect function
|
||||
if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
|
||||
}
|
||||
|
||||
SEGENV.next_time = nowUp + delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
_virtualSegmentLength = 0;
|
||||
if(doShow) {
|
||||
yield();
|
||||
show();
|
||||
}
|
||||
_triggered = false;
|
||||
}
|
||||
|
||||
void WS2812FX::setPixelColor(uint16_t n, uint32_t c) {
|
||||
uint8_t w = (c >> 24);
|
||||
uint8_t r = (c >> 16);
|
||||
uint8_t g = (c >> 8);
|
||||
uint8_t b = c ;
|
||||
setPixelColor(n, r, g, b, w);
|
||||
}
|
||||
|
||||
#define REV(i) (_length - 1 - (i))
|
||||
|
||||
//used to map from segment index to physical pixel, taking into account grouping, offsets, reverse and mirroring
|
||||
uint16_t WS2812FX::realPixelIndex(uint16_t i) {
|
||||
int16_t iGroup = i * SEGMENT.groupLength();
|
||||
|
||||
/* reverse just an individual segment */
|
||||
int16_t realIndex = iGroup;
|
||||
if (IS_REVERSE) {
|
||||
if (IS_MIRROR) {
|
||||
realIndex = (SEGMENT.length() -1) / 2 - iGroup; //only need to index half the pixels
|
||||
} else {
|
||||
realIndex = SEGMENT.length() - iGroup - 1;
|
||||
}
|
||||
}
|
||||
|
||||
realIndex += SEGMENT.start;
|
||||
/* Reverse the whole string */
|
||||
if (reverseMode) realIndex = REV(realIndex);
|
||||
|
||||
return realIndex;
|
||||
}
|
||||
|
||||
void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
//auto calculate white channel value if enabled
|
||||
if (_useRgbw) {
|
||||
if (rgbwMode == RGBW_MODE_AUTO_BRIGHTER || (w == 0 && (rgbwMode == RGBW_MODE_DUAL || rgbwMode == RGBW_MODE_LEGACY)))
|
||||
{
|
||||
//white value is set to lowest RGB channel
|
||||
//thank you to @Def3nder!
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
} else if (rgbwMode == RGBW_MODE_AUTO_ACCURATE && w == 0)
|
||||
{
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
r -= w; g -= w; b -= w;
|
||||
}
|
||||
}
|
||||
|
||||
//reorder channels to selected order
|
||||
RgbwColor col;
|
||||
switch (colorOrder)
|
||||
{
|
||||
case 0: col.G = g; col.R = r; col.B = b; break; //0 = GRB, default
|
||||
case 1: col.G = r; col.R = g; col.B = b; break; //1 = RGB, common for WS2811
|
||||
case 2: col.G = b; col.R = r; col.B = g; break; //2 = BRG
|
||||
case 3: col.G = r; col.R = b; col.B = g; break; //3 = RBG
|
||||
case 4: col.G = b; col.R = g; col.B = r; break; //4 = BGR
|
||||
default: col.G = g; col.R = b; col.B = r; break; //5 = GBR
|
||||
}
|
||||
col.W = w;
|
||||
|
||||
uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0;
|
||||
if (SEGLEN) {//from segment
|
||||
|
||||
//color_blend(getpixel, col, SEGMENT.opacity); (pseudocode for future blending of segments)
|
||||
if (IS_SEGMENT_ON)
|
||||
{
|
||||
if (SEGMENT.opacity < 255) {
|
||||
col.R = scale8(col.R, SEGMENT.opacity);
|
||||
col.G = scale8(col.G, SEGMENT.opacity);
|
||||
col.B = scale8(col.B, SEGMENT.opacity);
|
||||
col.W = scale8(col.W, SEGMENT.opacity);
|
||||
}
|
||||
} else {
|
||||
col = BLACK;
|
||||
}
|
||||
|
||||
/* Set all the pixels in the group, ensuring _skipFirstMode is honored */
|
||||
bool reversed = reverseMode ^ IS_REVERSE;
|
||||
uint16_t realIndex = realPixelIndex(i);
|
||||
|
||||
for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
|
||||
int16_t indexSet = realIndex + (reversed ? -j : j);
|
||||
int16_t indexSetRev = indexSet;
|
||||
if (reverseMode) indexSetRev = REV(indexSet);
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
|
||||
#endif
|
||||
if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) {
|
||||
bus->SetPixelColor(indexSet + skip, col);
|
||||
if (IS_MIRROR) { //set the corresponding mirrored pixel
|
||||
if (reverseMode) {
|
||||
bus->SetPixelColor(REV(SEGMENT.start) - indexSet + skip + REV(SEGMENT.stop) + 1, col);
|
||||
} else {
|
||||
bus->SetPixelColor(SEGMENT.stop - indexSet + skip + SEGMENT.start - 1, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { //live data, etc.
|
||||
if (reverseMode) i = REV(i);
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
#endif
|
||||
bus->SetPixelColor(i + skip, col);
|
||||
}
|
||||
if (skip && i == 0) {
|
||||
for (uint16_t j = 0; j < skip; j++) {
|
||||
bus->SetPixelColor(j, RgbwColor(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//DISCLAIMER
|
||||
//The following function attemps to calculate the current LED power usage,
|
||||
//and will limit the brightness to stay below a set amperage threshold.
|
||||
//It is NOT a measurement and NOT guaranteed to stay within the ablMilliampsMax margin.
|
||||
//Stay safe with high amperage and have a reasonable safety margin!
|
||||
//I am NOT to be held liable for burned down garages!
|
||||
|
||||
//fine tune power estimation constants for your setup
|
||||
#define MA_FOR_ESP 100 //how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA)
|
||||
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
|
||||
|
||||
void WS2812FX::show(void) {
|
||||
if (_callback) _callback();
|
||||
|
||||
//power limit calculation
|
||||
//each LED can draw up 195075 "power units" (approx. 53mA)
|
||||
//one PU is the power it takes to have 1 channel 1 step brighter per brightness step
|
||||
//so A=2,R=255,G=0,B=0 would use 510 PU per LED (1mA is about 3700 PU)
|
||||
bool useWackyWS2815PowerModel = false;
|
||||
byte actualMilliampsPerLed = milliampsPerLed;
|
||||
|
||||
if(milliampsPerLed == 255) {
|
||||
useWackyWS2815PowerModel = true;
|
||||
actualMilliampsPerLed = 12; // from testing an actual strip
|
||||
}
|
||||
|
||||
if (ablMilliampsMax > 149 && actualMilliampsPerLed > 0) //0 mA per LED and too low numbers turn off calculation
|
||||
{
|
||||
uint32_t puPerMilliamp = 195075 / actualMilliampsPerLed;
|
||||
uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * puPerMilliamp; //100mA for ESP power
|
||||
if (powerBudget > puPerMilliamp * _length) //each LED uses about 1mA in standby, exclude that from power budget
|
||||
{
|
||||
powerBudget -= puPerMilliamp * _length;
|
||||
} else
|
||||
{
|
||||
powerBudget = 0;
|
||||
}
|
||||
|
||||
uint32_t powerSum = 0;
|
||||
|
||||
for (uint16_t i = 0; i < _length; i++) //sum up the usage of each LED
|
||||
{
|
||||
RgbwColor c = bus->GetPixelColorRgbw(i);
|
||||
|
||||
if(useWackyWS2815PowerModel)
|
||||
{
|
||||
// ignore white component on WS2815 power calculation
|
||||
powerSum += (MAX(MAX(c.R,c.G),c.B)) * 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
powerSum += (c.R + c.G + c.B + c.W);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_useRgbw) //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
{
|
||||
powerSum *= 3;
|
||||
powerSum = powerSum >> 2; //same as /= 4
|
||||
}
|
||||
|
||||
uint32_t powerSum0 = powerSum;
|
||||
powerSum *= _brightness;
|
||||
|
||||
if (powerSum > powerBudget) //scale brightness down to stay in current limit
|
||||
{
|
||||
float scale = (float)powerBudget / (float)powerSum;
|
||||
uint16_t scaleI = scale * 255;
|
||||
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
|
||||
uint8_t newBri = scale8(_brightness, scaleB);
|
||||
bus->SetBrightness(newBri);
|
||||
currentMilliamps = (powerSum0 * newBri) / puPerMilliamp;
|
||||
} else
|
||||
{
|
||||
currentMilliamps = powerSum / puPerMilliamp;
|
||||
bus->SetBrightness(_brightness);
|
||||
}
|
||||
currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate
|
||||
currentMilliamps += _length; //add standby power back to estimate
|
||||
} else {
|
||||
currentMilliamps = 0;
|
||||
bus->SetBrightness(_brightness);
|
||||
}
|
||||
|
||||
bus->Show();
|
||||
_lastShow = millis();
|
||||
}
|
||||
|
||||
void WS2812FX::trigger() {
|
||||
_triggered = true;
|
||||
}
|
||||
|
||||
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
||||
if (segid >= MAX_NUM_SEGMENTS) return;
|
||||
|
||||
if (m >= MODE_COUNT) m = MODE_COUNT - 1;
|
||||
|
||||
if (_segments[segid].mode != m)
|
||||
{
|
||||
_segment_runtimes[segid].reset();
|
||||
_segments[segid].mode = m;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getModeCount()
|
||||
{
|
||||
return MODE_COUNT;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getPaletteCount()
|
||||
{
|
||||
return 13 + GRADIENT_PALETTE_COUNT;
|
||||
}
|
||||
|
||||
//TODO transitions
|
||||
|
||||
|
||||
bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
|
||||
uint8_t mainSeg = getMainSegmentId();
|
||||
Segment& seg = _segments[getMainSegmentId()];
|
||||
uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette;
|
||||
|
||||
bool applied = false;
|
||||
|
||||
if (applyToAllSelected) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected())
|
||||
{
|
||||
_segments[i].speed = s;
|
||||
_segments[i].intensity = in;
|
||||
_segments[i].palette = p;
|
||||
setMode(i, m);
|
||||
applied = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!applyToAllSelected || !applied) {
|
||||
seg.speed = s;
|
||||
seg.intensity = in;
|
||||
seg.palette = p;
|
||||
setMode(mainSegment, m);
|
||||
}
|
||||
|
||||
if (seg.mode != modePrev || seg.speed != speedPrev || seg.intensity != intensityPrev || seg.palette != palettePrev) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void WS2812FX::setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
||||
setColor(slot, ((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
|
||||
}
|
||||
|
||||
void WS2812FX::setColor(uint8_t slot, uint32_t c) {
|
||||
if (slot >= NUM_COLORS) return;
|
||||
|
||||
bool applied = false;
|
||||
|
||||
if (applyToAllSelected) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) _segments[i].colors[slot] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (!applyToAllSelected || !applied) {
|
||||
_segments[getMainSegmentId()].colors[slot] = c;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setBrightness(uint8_t b) {
|
||||
if (_brightness == b) return;
|
||||
_brightness = (gammaCorrectBri) ? gamma8(b) : b;
|
||||
_segment_index = 0;
|
||||
if (b == 0) { //unfreeze all segments on power off
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segments[i].setOption(SEG_OPTION_FREEZE, false);
|
||||
}
|
||||
}
|
||||
if (SEGENV.next_time > millis() + 22 && millis() - _lastShow > MIN_SHOW_DELAY) show();//apply brightness change immediately if no refresh soon
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getMode(void) {
|
||||
return _segments[getMainSegmentId()].mode;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getSpeed(void) {
|
||||
return _segments[getMainSegmentId()].speed;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getBrightness(void) {
|
||||
return _brightness;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getMaxSegments(void) {
|
||||
return MAX_NUM_SEGMENTS;
|
||||
}
|
||||
|
||||
/*uint8_t WS2812FX::getFirstSelectedSegment(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isActive() && _segments[i].isSelected()) return i;
|
||||
}
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) //if none selected, get first active
|
||||
{
|
||||
if (_segments[i].isActive()) return i;
|
||||
}
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
uint8_t WS2812FX::getMainSegmentId(void) {
|
||||
if (mainSegment >= MAX_NUM_SEGMENTS) return 0;
|
||||
if (_segments[mainSegment].isActive()) return mainSegment;
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) //get first active
|
||||
{
|
||||
if (_segments[i].isActive()) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getColor(void) {
|
||||
return _segments[getMainSegmentId()].colors[0];
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||
{
|
||||
i = realPixelIndex(i);
|
||||
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
#endif
|
||||
|
||||
if (_skipFirstMode) i += LED_SKIP_AMOUNT;
|
||||
|
||||
if (i >= _lengthRaw) return 0;
|
||||
|
||||
RgbwColor col = bus->GetPixelColorRgbw(i);
|
||||
switch (colorOrder)
|
||||
{
|
||||
// W G R B
|
||||
case 0: return ((col.W << 24) | (col.G << 8) | (col.R << 16) | (col.B)); //0 = GRB, default
|
||||
case 1: return ((col.W << 24) | (col.R << 8) | (col.G << 16) | (col.B)); //1 = RGB, common for WS2811
|
||||
case 2: return ((col.W << 24) | (col.B << 8) | (col.R << 16) | (col.G)); //2 = BRG
|
||||
case 3: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //3 = RBG
|
||||
case 4: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //4 = BGR
|
||||
case 5: return ((col.W << 24) | (col.G << 8) | (col.B << 16) | (col.R)); //5 = GBR
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
|
||||
if (id >= MAX_NUM_SEGMENTS) return _segments[0];
|
||||
return _segments[id];
|
||||
}
|
||||
|
||||
WS2812FX::Segment_runtime WS2812FX::getSegmentRuntime(void) {
|
||||
return SEGENV;
|
||||
}
|
||||
|
||||
WS2812FX::Segment* WS2812FX::getSegments(void) {
|
||||
return _segments;
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getLastShow(void) {
|
||||
return _lastShow;
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
|
||||
if (n >= MAX_NUM_SEGMENTS) return;
|
||||
Segment& seg = _segments[n];
|
||||
|
||||
//return if neither bounds nor grouping have changed
|
||||
if (seg.start == i1 && seg.stop == i2 && (!grouping || (seg.grouping == grouping && seg.spacing == spacing))) return;
|
||||
|
||||
if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off
|
||||
if (i2 <= i1) //disable segment
|
||||
{
|
||||
seg.stop = 0;
|
||||
if (n == mainSegment) //if main segment is deleted, set first active as main segment
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isActive()) {
|
||||
mainSegment = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mainSegment = 0; //should not happen (always at least one active segment)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (i1 < _length) seg.start = i1;
|
||||
seg.stop = i2;
|
||||
if (i2 > _length) seg.stop = _length;
|
||||
if (grouping) {
|
||||
seg.grouping = grouping;
|
||||
seg.spacing = spacing;
|
||||
}
|
||||
_segment_runtimes[n].reset();
|
||||
}
|
||||
|
||||
void WS2812FX::resetSegments() {
|
||||
mainSegment = 0;
|
||||
memset(_segments, 0, sizeof(_segments));
|
||||
//memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
|
||||
_segment_index = 0;
|
||||
_segments[0].mode = DEFAULT_MODE;
|
||||
_segments[0].colors[0] = DEFAULT_COLOR;
|
||||
_segments[0].start = 0;
|
||||
_segments[0].speed = DEFAULT_SPEED;
|
||||
_segments[0].stop = _length;
|
||||
_segments[0].grouping = 1;
|
||||
_segments[0].setOption(SEG_OPTION_SELECTED, 1);
|
||||
_segments[0].setOption(SEG_OPTION_ON, 1);
|
||||
_segments[0].opacity = 255;
|
||||
|
||||
for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segments[i].colors[0] = color_wheel(i*51);
|
||||
_segments[i].grouping = 1;
|
||||
_segments[i].setOption(SEG_OPTION_ON, 1);
|
||||
_segments[i].opacity = 255;
|
||||
_segment_runtimes[i].reset();
|
||||
}
|
||||
_segment_runtimes[0].reset();
|
||||
}
|
||||
|
||||
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
|
||||
void WS2812FX::setPixelSegment(uint8_t n)
|
||||
{
|
||||
if (n < MAX_NUM_SEGMENTS) {
|
||||
_segment_index = n;
|
||||
_virtualSegmentLength = SEGMENT.length();
|
||||
} else {
|
||||
_segment_index = 0;
|
||||
_virtualSegmentLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
|
||||
{
|
||||
if (i2 >= i)
|
||||
{
|
||||
for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col);
|
||||
} else
|
||||
{
|
||||
for (uint16_t x = i2; x <= i; x++) setPixelColor(x, col);
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setShowCallback(show_callback cb)
|
||||
{
|
||||
_callback = cb;
|
||||
}
|
||||
|
||||
void WS2812FX::setTransitionMode(bool t)
|
||||
{
|
||||
unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled
|
||||
for (uint16_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segment_index = i;
|
||||
SEGMENT.setOption(SEG_OPTION_TRANSITIONAL, t);
|
||||
|
||||
if (t && SEGMENT.mode == FX_MODE_STATIC && SEGENV.next_time > waitMax) SEGENV.next_time = waitMax;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* color blend function
|
||||
*/
|
||||
uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint8_t blend) {
|
||||
if(blend == 0) return color1;
|
||||
if(blend == 255) return color2;
|
||||
|
||||
uint32_t w1 = (color1 >> 24) & 0xff;
|
||||
uint32_t r1 = (color1 >> 16) & 0xff;
|
||||
uint32_t g1 = (color1 >> 8) & 0xff;
|
||||
uint32_t b1 = color1 & 0xff;
|
||||
|
||||
uint32_t w2 = (color2 >> 24) & 0xff;
|
||||
uint32_t r2 = (color2 >> 16) & 0xff;
|
||||
uint32_t g2 = (color2 >> 8) & 0xff;
|
||||
uint32_t b2 = color2 & 0xff;
|
||||
|
||||
uint32_t w3 = ((w2 * blend) + (w1 * (255 - blend))) >> 8;
|
||||
uint32_t r3 = ((r2 * blend) + (r1 * (255 - blend))) >> 8;
|
||||
uint32_t g3 = ((g2 * blend) + (g1 * (255 - blend))) >> 8;
|
||||
uint32_t b3 = ((b2 * blend) + (b1 * (255 - blend))) >> 8;
|
||||
|
||||
return ((w3 << 24) | (r3 << 16) | (g3 << 8) | (b3));
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills segment with color
|
||||
*/
|
||||
void WS2812FX::fill(uint32_t c) {
|
||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||
setPixelColor(i, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Blends the specified color with the existing pixel color.
|
||||
*/
|
||||
void WS2812FX::blendPixelColor(uint16_t n, uint32_t color, uint8_t blend)
|
||||
{
|
||||
setPixelColor(n, color_blend(getPixelColor(n), color, blend));
|
||||
}
|
||||
|
||||
/*
|
||||
* fade out function, higher rate = quicker fade
|
||||
*/
|
||||
void WS2812FX::fade_out(uint8_t rate) {
|
||||
rate = (255-rate) >> 1;
|
||||
float mappedRate = float(rate) +1.1;
|
||||
|
||||
uint32_t color = SEGCOLOR(1); // target color
|
||||
int w2 = (color >> 24) & 0xff;
|
||||
int r2 = (color >> 16) & 0xff;
|
||||
int g2 = (color >> 8) & 0xff;
|
||||
int b2 = color & 0xff;
|
||||
|
||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||
color = getPixelColor(i);
|
||||
int w1 = (color >> 24) & 0xff;
|
||||
int r1 = (color >> 16) & 0xff;
|
||||
int g1 = (color >> 8) & 0xff;
|
||||
int b1 = color & 0xff;
|
||||
|
||||
int wdelta = (w2 - w1) / mappedRate;
|
||||
int rdelta = (r2 - r1) / mappedRate;
|
||||
int gdelta = (g2 - g1) / mappedRate;
|
||||
int bdelta = (b2 - b1) / mappedRate;
|
||||
|
||||
// if fade isn't complete, make sure delta is at least 1 (fixes rounding issues)
|
||||
wdelta += (w2 == w1) ? 0 : (w2 > w1) ? 1 : -1;
|
||||
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
||||
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
||||
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
|
||||
|
||||
setPixelColor(i, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* blurs segment content, source: FastLED colorutils.cpp
|
||||
*/
|
||||
void WS2812FX::blur(uint8_t blur_amount)
|
||||
{
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
for(uint16_t i = 0; i < SEGLEN; i++)
|
||||
{
|
||||
CRGB cur = col_to_crgb(getPixelColor(i));
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if(i > 0) {
|
||||
uint32_t c = getPixelColor(i-1);
|
||||
uint8_t r = (c >> 16 & 0xFF);
|
||||
uint8_t g = (c >> 8 & 0xFF);
|
||||
uint8_t b = (c & 0xFF);
|
||||
setPixelColor(i-1, qadd8(r, part.red), qadd8(g, part.green), qadd8(b, part.blue));
|
||||
}
|
||||
setPixelColor(i,cur.red, cur.green, cur.blue);
|
||||
carryover = part;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::triwave16(uint16_t in)
|
||||
{
|
||||
if (in < 0x8000) return in *2;
|
||||
return 0xFFFF - (in - 0x8000)*2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a value 0 to 255 in to get a color value.
|
||||
* The colours are a transition r -> g -> b -> back to r
|
||||
* Inspired by the Adafruit examples.
|
||||
*/
|
||||
uint32_t WS2812FX::color_wheel(uint8_t pos) {
|
||||
if (SEGMENT.palette) return color_from_palette(pos, false, true, 0);
|
||||
pos = 255 - pos;
|
||||
if(pos < 85) {
|
||||
return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
|
||||
} else if(pos < 170) {
|
||||
pos -= 85;
|
||||
return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3);
|
||||
} else {
|
||||
pos -= 170;
|
||||
return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new, random wheel index with a minimum distance of 42 from pos.
|
||||
*/
|
||||
uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) {
|
||||
uint8_t r = 0, x = 0, y = 0, d = 0;
|
||||
|
||||
while(d < 42) {
|
||||
r = random8();
|
||||
x = abs(pos - r);
|
||||
y = 255 - x;
|
||||
d = MIN(x, y);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
uint32_t WS2812FX::crgb_to_col(CRGB fastled)
|
||||
{
|
||||
return (((uint32_t)fastled.red << 16) | ((uint32_t)fastled.green << 8) | fastled.blue);
|
||||
}
|
||||
|
||||
|
||||
CRGB WS2812FX::col_to_crgb(uint32_t color)
|
||||
{
|
||||
CRGB fastled_col;
|
||||
fastled_col.red = (color >> 16 & 0xFF);
|
||||
fastled_col.green = (color >> 8 & 0xFF);
|
||||
fastled_col.blue = (color & 0xFF);
|
||||
return fastled_col;
|
||||
}
|
||||
|
||||
|
||||
void WS2812FX::load_gradient_palette(uint8_t index)
|
||||
{
|
||||
byte i = constrain(index, 0, GRADIENT_PALETTE_COUNT -1);
|
||||
byte tcp[72]; //support gradient palettes with up to 18 entries
|
||||
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i])), 72);
|
||||
targetPalette.loadDynamicGradientPalette(tcp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FastLED palette modes helper function. Limitation: Due to memory reasons, multiple active segments with FastLED will disable the Palette transitions
|
||||
*/
|
||||
void WS2812FX::handle_palette(void)
|
||||
{
|
||||
bool singleSegmentMode = (_segment_index == _segment_index_palette_last);
|
||||
_segment_index_palette_last = _segment_index;
|
||||
|
||||
byte paletteIndex = SEGMENT.palette;
|
||||
if (paletteIndex == 0) //default palette. Differs depending on effect
|
||||
{
|
||||
switch (SEGMENT.mode)
|
||||
{
|
||||
case FX_MODE_FIRE_2012 : paletteIndex = 35; break; //heat palette
|
||||
case FX_MODE_COLORWAVES : paletteIndex = 26; break; //landscape 33
|
||||
case FX_MODE_FILLNOISE8 : paletteIndex = 9; break; //ocean colors
|
||||
case FX_MODE_NOISE16_1 : paletteIndex = 20; break; //Drywet
|
||||
case FX_MODE_NOISE16_2 : paletteIndex = 43; break; //Blue cyan yellow
|
||||
case FX_MODE_NOISE16_3 : paletteIndex = 35; break; //heat palette
|
||||
case FX_MODE_NOISE16_4 : paletteIndex = 26; break; //landscape 33
|
||||
case FX_MODE_GLITTER : paletteIndex = 11; break; //rainbow colors
|
||||
case FX_MODE_SUNRISE : paletteIndex = 35; break; //heat palette
|
||||
case FX_MODE_FLOW : paletteIndex = 6; break; //party
|
||||
}
|
||||
}
|
||||
if (SEGMENT.mode >= FX_MODE_METEOR && paletteIndex == 0) paletteIndex = 4;
|
||||
|
||||
switch (paletteIndex)
|
||||
{
|
||||
case 0: //default palette. Exceptions for specific effects above
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 1: {//periodically replace palette with a random one. Doesn't work with multiple FastLED segments
|
||||
if (!singleSegmentMode)
|
||||
{
|
||||
targetPalette = PartyColors_p; break; //fallback
|
||||
}
|
||||
if (millis() - _lastPaletteChange > 1000 + ((uint32_t)(255-SEGMENT.intensity))*100)
|
||||
{
|
||||
targetPalette = CRGBPalette16(
|
||||
CHSV(random8(), 255, random8(128, 255)),
|
||||
CHSV(random8(), 255, random8(128, 255)),
|
||||
CHSV(random8(), 192, random8(128, 255)),
|
||||
CHSV(random8(), 255, random8(128, 255)));
|
||||
_lastPaletteChange = millis();
|
||||
} break;}
|
||||
case 2: {//primary color only
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
targetPalette = CRGBPalette16(prim); break;}
|
||||
case 3: {//primary + secondary
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
|
||||
case 4: {//primary + secondary + tertiary
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
CRGB ter = col_to_crgb(SEGCOLOR(2));
|
||||
targetPalette = CRGBPalette16(ter,sec,prim); break;}
|
||||
case 5: {//primary + secondary (+tert if not off), more distinct
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
if (SEGCOLOR(2)) {
|
||||
CRGB ter = col_to_crgb(SEGCOLOR(2));
|
||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
|
||||
} else {
|
||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
|
||||
}
|
||||
break;}
|
||||
case 6: //Party colors
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 7: //Cloud colors
|
||||
targetPalette = CloudColors_p; break;
|
||||
case 8: //Lava colors
|
||||
targetPalette = LavaColors_p; break;
|
||||
case 9: //Ocean colors
|
||||
targetPalette = OceanColors_p; break;
|
||||
case 10: //Forest colors
|
||||
targetPalette = ForestColors_p; break;
|
||||
case 11: //Rainbow colors
|
||||
targetPalette = RainbowColors_p; break;
|
||||
case 12: //Rainbow stripe colors
|
||||
targetPalette = RainbowStripeColors_p; break;
|
||||
default: //progmem palettes
|
||||
load_gradient_palette(paletteIndex -13);
|
||||
}
|
||||
|
||||
if (singleSegmentMode && paletteFade) //only blend if just one segment uses FastLED mode
|
||||
{
|
||||
nblendPaletteTowardPalette(currentPalette, targetPalette, 48);
|
||||
} else
|
||||
{
|
||||
currentPalette = targetPalette;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Gets a single color from the currently selected palette.
|
||||
* @param i Palette Index (if mapping is true, the full palette will be SEGLEN long, if false, 255). Will wrap around automatically.
|
||||
* @param mapping if true, LED position in segment is considered for color
|
||||
* @param wrap FastLED palettes will usally wrap back to the start smoothly. Set false to get a hard edge
|
||||
* @param mcol If the default palette 0 is selected, return the standard color 0, 1 or 2 instead. If >2, Party palette is used instead
|
||||
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
|
||||
* @returns Single color from palette
|
||||
*/
|
||||
uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri)
|
||||
{
|
||||
if (SEGMENT.palette == 0 && mcol < 3) return SEGCOLOR(mcol); //WS2812FX default
|
||||
uint8_t paletteIndex = i;
|
||||
if (mapping) paletteIndex = (i*255)/(SEGLEN -1);
|
||||
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||
CRGB fastled_col;
|
||||
fastled_col = ColorFromPalette( currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
||||
return fastled_col.r*65536 + fastled_col.g*256 + fastled_col.b;
|
||||
}
|
||||
|
||||
//@returns `true` if color, mode, speed, intensity and palette match
|
||||
bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
|
||||
{
|
||||
//if (a->start != b->start) return false;
|
||||
//if (a->stop != b->stop) return false;
|
||||
for (uint8_t i = 0; i < NUM_COLORS; i++)
|
||||
{
|
||||
if (a->colors[i] != b->colors[i]) return false;
|
||||
}
|
||||
if (a->mode != b->mode) return false;
|
||||
if (a->speed != b->speed) return false;
|
||||
if (a->intensity != b->intensity) return false;
|
||||
if (a->palette != b->palette) return false;
|
||||
//if (a->getOption(SEG_OPTION_REVERSED) != b->getOption(SEG_OPTION_REVERSED)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
void WS2812FX::setRgbwPwm(void) {
|
||||
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
|
||||
if (nowUp - _analogLastShow < MIN_SHOW_DELAY) return;
|
||||
|
||||
_analogLastShow = nowUp;
|
||||
|
||||
RgbwColor color = bus->GetPixelColorRgbw(0);
|
||||
byte b = getBrightness();
|
||||
if (color == _analogLastColor && b == _analogLastBri) return;
|
||||
|
||||
// check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
if (color.R == 255 && color.G == 255 && color.B == 255 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, 0, color.W * b / 255);
|
||||
} else if (color.R == 127 && color.G == 127 && color.B == 127 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 512, color.W * b / 255);
|
||||
} else if (color.R == 0 && color.G == 0 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else if (color.R == 130 && color.G == 90 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512);
|
||||
} else if (color.R == 255 && color.G == 153 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else { // not only white colors
|
||||
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
|
||||
}
|
||||
#else
|
||||
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
|
||||
#endif
|
||||
_analogLastColor = color;
|
||||
_analogLastBri = b;
|
||||
}
|
||||
#else
|
||||
void WS2812FX::setRgbwPwm() {}
|
||||
#endif
|
||||
|
||||
//gamma 2.4 lookup table used for color correction
|
||||
const byte gammaT[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
||||
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
|
||||
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
|
||||
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
|
||||
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
|
||||
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
|
||||
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
|
||||
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
|
||||
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
|
||||
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
|
||||
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
|
||||
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
|
||||
|
||||
uint8_t WS2812FX::gamma8(uint8_t b)
|
||||
{
|
||||
return gammaT[b];
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::gamma32(uint32_t color)
|
||||
{
|
||||
if (!gammaCorrectCol) return color;
|
||||
uint8_t w = (color >> 24);
|
||||
uint8_t r = (color >> 16);
|
||||
uint8_t g = (color >> 8);
|
||||
uint8_t b = color;
|
||||
w = gammaT[w];
|
||||
r = gammaT[r];
|
||||
g = gammaT[g];
|
||||
b = gammaT[b];
|
||||
return ((w << 24) | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::_usedSegmentData = 0;
|
348
wled00/NpbWrapper.h
Normal file
@@ -0,0 +1,348 @@
|
||||
//this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103
|
||||
#ifndef NpbWrapper_h
|
||||
#define NpbWrapper_h
|
||||
|
||||
//PIN CONFIGURATION
|
||||
#ifndef LEDPIN
|
||||
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
|
||||
#endif
|
||||
//#define USE_APA102 // Uncomment for using APA102 LEDs.
|
||||
//#define USE_WS2801 // Uncomment for using WS2801 LEDs (make sure you have NeoPixelBus v2.5.6 or newer)
|
||||
//#define USE_LPD8806 // Uncomment for using LPD8806
|
||||
//#define USE_TM1814 // Uncomment for using TM1814 LEDs (make sure you have NeoPixelBus v2.5.7 or newer)
|
||||
//#define USE_P9813 // Uncomment for using P9813 LEDs (make sure you have NeoPixelBus v2.5.8 or newer)
|
||||
//#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13)
|
||||
//#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well
|
||||
//#define WLED_USE_5CH_LEDS //5 Channel H801 for cold and warm white
|
||||
//#define WLED_USE_BWLT11
|
||||
//#define WLED_USE_SHOJO_PCB
|
||||
|
||||
#ifndef BTNPIN
|
||||
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
|
||||
#endif
|
||||
|
||||
#ifndef IR_PIN
|
||||
#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
|
||||
#endif
|
||||
|
||||
#ifndef RLYPIN
|
||||
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
|
||||
#endif
|
||||
|
||||
#ifndef AUXPIN
|
||||
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)
|
||||
#endif
|
||||
|
||||
#ifndef RLYMDE
|
||||
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
|
||||
#endif
|
||||
|
||||
//END CONFIGURATION
|
||||
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
|
||||
#ifndef CLKPIN
|
||||
#define CLKPIN 0
|
||||
#endif
|
||||
#ifndef DATAPIN
|
||||
#define DATAPIN 2
|
||||
#endif
|
||||
#if BTNPIN == CLKPIN || BTNPIN == DATAPIN
|
||||
#undef BTNPIN // Deactivate button pin if it conflicts with one of the APA102 pins.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
//PWM pins - PINs 15,13,12,14 (W2 = 04)are used with H801 Wifi LED Controller
|
||||
#ifdef WLED_USE_H801
|
||||
#define RPIN 15 //R pin for analog LED strip
|
||||
#define GPIN 13 //G pin for analog LED strip
|
||||
#define BPIN 12 //B pin for analog LED strip
|
||||
#define WPIN 14 //W pin for analog LED strip
|
||||
#define W2PIN 04 //W2 pin for analog LED strip
|
||||
#undef BTNPIN
|
||||
#undef IR_PIN
|
||||
#define IR_PIN 0 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
|
||||
#elif defined(WLED_USE_BWLT11)
|
||||
//PWM pins - to use with BW-LT11
|
||||
#define RPIN 12 //R pin for analog LED strip
|
||||
#define GPIN 4 //G pin for analog LED strip
|
||||
#define BPIN 14 //B pin for analog LED strip
|
||||
#define WPIN 5 //W pin for analog LED strip
|
||||
#elif defined(WLED_USE_SHOJO_PCB)
|
||||
//PWM pins - to use with Shojo PCB (https://www.bastelbunker.de/esp-rgbww-wifi-led-controller-vbs-edition/)
|
||||
#define RPIN 14 //R pin for analog LED strip
|
||||
#define GPIN 4 //G pin for analog LED strip
|
||||
#define BPIN 5 //B pin for analog LED strip
|
||||
#define WPIN 15 //W pin for analog LED strip
|
||||
#define W2PIN 12 //W2 pin for analog LED strip
|
||||
#elif defined(WLED_USE_PLJAKOBS_PCB)
|
||||
// PWM pins - to use with esp_rgbww_controller from patrickjahns/pljakobs (https://github.com/pljakobs/esp_rgbww_controller)
|
||||
#define RPIN 12 //R pin for analog LED strip
|
||||
#define GPIN 13 //G pin for analog LED strip
|
||||
#define BPIN 14 //B pin for analog LED strip
|
||||
#define WPIN 4 //W pin for analog LED strip
|
||||
#define W2PIN 5 //W2 pin for analog LED strip
|
||||
#undef IR_PIN
|
||||
#else
|
||||
//PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
|
||||
#define RPIN 5 //R pin for analog LED strip
|
||||
#define GPIN 12 //G pin for analog LED strip
|
||||
#define BPIN 15 //B pin for analog LED strip
|
||||
#define WPIN 13 //W pin for analog LED strip
|
||||
#endif
|
||||
#undef RLYPIN
|
||||
#define RLYPIN -1 //disable as pin 12 is used by analog LEDs
|
||||
#endif
|
||||
|
||||
//automatically uses the right driver method for each platform
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef USE_APA102
|
||||
#define PIXELMETHOD DotStarMethod
|
||||
#elif defined(USE_WS2801)
|
||||
#define PIXELMETHOD NeoWs2801Method
|
||||
#elif defined(USE_LPD8806)
|
||||
#define PIXELMETHOD Lpd8806Method
|
||||
#elif defined(USE_TM1814)
|
||||
#define PIXELMETHOD NeoTm1814Method
|
||||
#elif defined(USE_P9813)
|
||||
#define PIXELMETHOD P9813Method
|
||||
#else
|
||||
#define PIXELMETHOD NeoEsp32Rmt0Ws2812xMethod
|
||||
#endif
|
||||
#else //esp8266
|
||||
//autoselect the right method depending on strip pin
|
||||
#ifdef USE_APA102
|
||||
#define PIXELMETHOD DotStarMethod
|
||||
#elif defined(USE_WS2801)
|
||||
#define PIXELMETHOD NeoWs2801Method
|
||||
#elif defined(USE_LPD8806)
|
||||
#define PIXELMETHOD Lpd8806Method
|
||||
#elif defined(USE_TM1814)
|
||||
#define PIXELMETHOD NeoTm1814Method
|
||||
#elif defined(USE_P9813)
|
||||
#define PIXELMETHOD P9813Method
|
||||
#elif LEDPIN == 2
|
||||
#define PIXELMETHOD NeoEsp8266Uart1Ws2813Method //if you get an error here, try to change to NeoEsp8266UartWs2813Method or update Neopixelbus
|
||||
#elif LEDPIN == 3
|
||||
#define PIXELMETHOD NeoEsp8266Dma800KbpsMethod
|
||||
#else
|
||||
#define PIXELMETHOD NeoEsp8266BitBang800KbpsMethod
|
||||
#pragma message "Software BitBang will be used because of your selected LED pin. This may cause flicker. Use GPIO 2 or 3 for best results."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//you can now change the color order in the web settings
|
||||
#ifdef USE_APA102
|
||||
#define PIXELFEATURE3 DotStarBgrFeature
|
||||
#define PIXELFEATURE4 DotStarLbgrFeature
|
||||
#elif defined(USE_LPD8806)
|
||||
#define PIXELFEATURE3 Lpd8806GrbFeature
|
||||
#elif defined(USE_WS2801)
|
||||
#define PIXELFEATURE3 NeoRbgFeature
|
||||
#define PIXELFEATURE4 NeoRbgFeature
|
||||
#elif defined(USE_TM1814)
|
||||
#define PIXELFEATURE3 NeoWrgbTm1814Feature
|
||||
#define PIXELFEATURE4 NeoWrgbTm1814Feature
|
||||
#elif defined(USE_P9813)
|
||||
#define PIXELFEATURE3 P9813BgrFeature
|
||||
#define PIXELFEATURE4 NeoGrbwFeature
|
||||
#else
|
||||
#define PIXELFEATURE3 NeoGrbFeature
|
||||
#define PIXELFEATURE4 NeoGrbwFeature
|
||||
#endif
|
||||
|
||||
|
||||
#include <NeoPixelBrightnessBus.h>
|
||||
|
||||
enum NeoPixelType
|
||||
{
|
||||
NeoPixelType_None = 0,
|
||||
NeoPixelType_Grb = 1,
|
||||
NeoPixelType_Grbw = 2,
|
||||
NeoPixelType_End = 3
|
||||
};
|
||||
|
||||
class NeoPixelWrapper
|
||||
{
|
||||
public:
|
||||
NeoPixelWrapper() :
|
||||
// initialize each member to null
|
||||
_pGrb(NULL),
|
||||
_pGrbw(NULL),
|
||||
_type(NeoPixelType_None)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~NeoPixelWrapper()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void Begin(NeoPixelType type, uint16_t countPixels)
|
||||
{
|
||||
cleanup();
|
||||
_type = type;
|
||||
|
||||
switch (_type)
|
||||
{
|
||||
case NeoPixelType_Grb:
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
|
||||
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
|
||||
#else
|
||||
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, LEDPIN);
|
||||
#endif
|
||||
_pGrb->Begin();
|
||||
break;
|
||||
|
||||
case NeoPixelType_Grbw:
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
|
||||
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
|
||||
#else
|
||||
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, LEDPIN);
|
||||
#endif
|
||||
_pGrbw->Begin();
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
ledcSetup(0, 5000, 8);
|
||||
ledcAttachPin(RPIN, 0);
|
||||
ledcSetup(1, 5000, 8);
|
||||
ledcAttachPin(GPIN, 1);
|
||||
ledcSetup(2, 5000, 8);
|
||||
ledcAttachPin(BPIN, 2);
|
||||
if(_type == NeoPixelType_Grbw)
|
||||
{
|
||||
ledcSetup(3, 5000, 8);
|
||||
ledcAttachPin(WPIN, 3);
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
ledcSetup(4, 5000, 8);
|
||||
ledcAttachPin(W2PIN, 4);
|
||||
#endif
|
||||
}
|
||||
#else // ESP8266
|
||||
//init PWM pins
|
||||
pinMode(RPIN, OUTPUT);
|
||||
pinMode(GPIN, OUTPUT);
|
||||
pinMode(BPIN, OUTPUT);
|
||||
if(_type == NeoPixelType_Grbw)
|
||||
{
|
||||
pinMode(WPIN, OUTPUT);
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
pinMode(W2PIN, OUTPUT);
|
||||
#endif
|
||||
}
|
||||
analogWriteRange(255); //same range as one RGB channel
|
||||
analogWriteFreq(880); //PWM frequency proven as good for LEDs
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
void SetRgbwPwm(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t w2=0)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
ledcWrite(0, r);
|
||||
ledcWrite(1, g);
|
||||
ledcWrite(2, b);
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
case NeoPixelType_Grbw: ledcWrite(3, w); ledcWrite(4, w2); break;
|
||||
#else
|
||||
case NeoPixelType_Grbw: ledcWrite(3, w); break;
|
||||
#endif
|
||||
}
|
||||
#else // ESP8266
|
||||
analogWrite(RPIN, r);
|
||||
analogWrite(GPIN, g);
|
||||
analogWrite(BPIN, b);
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
case NeoPixelType_Grbw: analogWrite(WPIN, w); analogWrite(W2PIN, w2); break;
|
||||
#else
|
||||
case NeoPixelType_Grbw: analogWrite(WPIN, w); break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void Show()
|
||||
{
|
||||
byte b;
|
||||
switch (_type)
|
||||
{
|
||||
case NeoPixelType_Grb: _pGrb->Show(); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->Show(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelColor(uint16_t indexPixel, RgbwColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: {
|
||||
_pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B));
|
||||
}
|
||||
break;
|
||||
case NeoPixelType_Grbw: {
|
||||
#if defined(USE_LPD8806) || defined(USE_WS2801)
|
||||
_pGrbw->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B));
|
||||
#else
|
||||
_pGrbw->SetPixelColor(indexPixel, color);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetBrightness(byte b)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetBrightness(b); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->SetBrightness(b); break;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Due to feature differences, some support RGBW but the method name
|
||||
// here needs to be unique, thus GetPixeColorRgbw
|
||||
RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
|
||||
case NeoPixelType_Grbw: return _pGrbw->GetPixelColor(indexPixel); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* GetPixels(void)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->Pixels(); break;
|
||||
case NeoPixelType_Grbw: return _pGrbw->Pixels(); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
NeoPixelType _type;
|
||||
|
||||
// have a member for every possible type
|
||||
NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>* _pGrb;
|
||||
NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>* _pGrbw;
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: delete _pGrb ; _pGrb = NULL; break;
|
||||
case NeoPixelType_Grbw: delete _pGrbw; _pGrbw = NULL; break;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
2174
wled00/WS2812FX.cpp
@@ -1,422 +0,0 @@
|
||||
//#define RGBW
|
||||
#define PIN 2 //strip pin. Only change for ESP32
|
||||
#define WORKAROUND_ESP32_BITBANG
|
||||
//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support
|
||||
|
||||
//automatically uses the right driver method for each platform
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef WORKAROUND_ESP32_BITBANG
|
||||
#define PIXELMETHOD NeoEsp32BitBangWs2813Method
|
||||
#else
|
||||
#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method
|
||||
#endif
|
||||
#else
|
||||
#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod
|
||||
#endif
|
||||
|
||||
//selects correct feature for RGB/RGBW
|
||||
#ifdef RGBW
|
||||
#define PIXELFEATURE NeoGrbwFeature
|
||||
#else
|
||||
#define PIXELFEATURE NeoGrbFeature
|
||||
#endif
|
||||
|
||||
/*
|
||||
WS2812FX.h - Library for WS2812 LED effects.
|
||||
|
||||
Harm Aldick - 2016
|
||||
www.aldick.org
|
||||
FEATURES
|
||||
* A lot of blinken modes and counting
|
||||
* WS2812FX can be used as drop-in replacement for Adafruit Neopixel Library
|
||||
NOTES
|
||||
* Uses the Adafruit Neopixel library. Get it here:
|
||||
https://github.com/adafruit/Adafruit_NeoPixel
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Harm Aldick
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
Modified to work with WLED - differs from Github WS2812FX
|
||||
*/
|
||||
|
||||
#ifndef WS2812FX_h
|
||||
#define WS2812FX_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <NeoPixelBrightnessBus.h>
|
||||
|
||||
#define DEFAULT_BRIGHTNESS 50
|
||||
#define DEFAULT_MODE 0
|
||||
#define DEFAULT_SPEED 150
|
||||
#define DEFAULT_COLOR 0xFFAA00
|
||||
|
||||
#define SPEED_MIN 0
|
||||
#define SPEED_MAX 255
|
||||
|
||||
#define BRIGHTNESS_MIN 0
|
||||
#define BRIGHTNESS_MAX 255
|
||||
|
||||
#define MODE_COUNT 58
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
#define FX_MODE_BREATH 2
|
||||
#define FX_MODE_COLOR_WIPE 3
|
||||
#define FX_MODE_COLOR_WIPE_RANDOM 4
|
||||
#define FX_MODE_RANDOM_COLOR 5
|
||||
#define FX_MODE_EASTER 6
|
||||
#define FX_MODE_DYNAMIC 7
|
||||
#define FX_MODE_RAINBOW 8
|
||||
#define FX_MODE_RAINBOW_CYCLE 9
|
||||
#define FX_MODE_SCAN 10
|
||||
#define FX_MODE_DUAL_SCAN 11
|
||||
#define FX_MODE_FADE 12
|
||||
#define FX_MODE_THEATER_CHASE 13
|
||||
#define FX_MODE_THEATER_CHASE_RAINBOW 14
|
||||
#define FX_MODE_RUNNING_LIGHTS 15
|
||||
#define FX_MODE_TWINKLE 16
|
||||
#define FX_MODE_TWINKLE_RANDOM 17
|
||||
#define FX_MODE_TWINKLE_FADE 18
|
||||
#define FX_MODE_TWINKLE_FADE_RANDOM 19
|
||||
#define FX_MODE_SPARKLE 20
|
||||
#define FX_MODE_FLASH_SPARKLE 21
|
||||
#define FX_MODE_HYPER_SPARKLE 22
|
||||
#define FX_MODE_STROBE 23
|
||||
#define FX_MODE_STROBE_RAINBOW 24
|
||||
#define FX_MODE_MULTI_STROBE 25
|
||||
#define FX_MODE_BLINK_RAINBOW 26
|
||||
#define FX_MODE_ANDROID 27
|
||||
#define FX_MODE_CHASE_COLOR 28
|
||||
#define FX_MODE_CHASE_RANDOM 29
|
||||
#define FX_MODE_CHASE_RAINBOW 30
|
||||
#define FX_MODE_CHASE_FLASH 31
|
||||
#define FX_MODE_CHASE_FLASH_RANDOM 32
|
||||
#define FX_MODE_CHASE_RAINBOW_WHITE 33
|
||||
#define FX_MODE_COLORFUL 34
|
||||
#define FX_MODE_TRAFFIC_LIGHT 35
|
||||
#define FX_MODE_COLOR_SWEEP_RANDOM 36
|
||||
#define FX_MODE_RUNNING_COLOR 37
|
||||
#define FX_MODE_RUNNING_RED_BLUE 38
|
||||
#define FX_MODE_RUNNING_RANDOM 39
|
||||
#define FX_MODE_LARSON_SCANNER 40
|
||||
#define FX_MODE_COMET 41
|
||||
#define FX_MODE_FIREWORKS 42
|
||||
#define FX_MODE_FIREWORKS_RANDOM 43
|
||||
#define FX_MODE_MERRY_CHRISTMAS 44
|
||||
#define FX_MODE_FIRE_FLICKER 45
|
||||
#define FX_MODE_GRADIENT 46
|
||||
#define FX_MODE_LOADING 47
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_IN_OUT 48
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_IN_IN 49
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_OUT_OUT 50
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_OUT_IN 51
|
||||
#define FX_MODE_CIRCUS_COMBUSTUS 52
|
||||
#define FX_MODE_CUSTOM_CHASE 53
|
||||
#define FX_MODE_CC_ON_RAINBOW 54
|
||||
#define FX_MODE_CC_ON_RAINBOW_CYCLE 55
|
||||
#define FX_MODE_CC_BLINK 56
|
||||
#define FX_MODE_CC_RANDOM 57
|
||||
|
||||
|
||||
class WS2812FX : public NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD> {
|
||||
typedef void (WS2812FX::*mode_ptr)(void);
|
||||
public:
|
||||
WS2812FX(uint16_t n) : NeoPixelBrightnessBus<PIXELFEATURE, PIXELMETHOD>(n,PIN) {
|
||||
|
||||
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
|
||||
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
|
||||
_mode[FX_MODE_BREATH] = &WS2812FX::mode_breath;
|
||||
_mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe;
|
||||
_mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random;
|
||||
_mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color;
|
||||
_mode[FX_MODE_EASTER] = &WS2812FX::mode_easter;
|
||||
_mode[FX_MODE_DYNAMIC] = &WS2812FX::mode_dynamic;
|
||||
_mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow;
|
||||
_mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle;
|
||||
_mode[FX_MODE_SCAN] = &WS2812FX::mode_scan;
|
||||
_mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan;
|
||||
_mode[FX_MODE_FADE] = &WS2812FX::mode_fade;
|
||||
_mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase;
|
||||
_mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow;
|
||||
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights;
|
||||
_mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle;
|
||||
_mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random;
|
||||
_mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade;
|
||||
_mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random;
|
||||
_mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle;
|
||||
_mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle;
|
||||
_mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle;
|
||||
_mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe;
|
||||
_mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow;
|
||||
_mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe;
|
||||
_mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow;
|
||||
_mode[FX_MODE_ANDROID] = &WS2812FX::mode_android;
|
||||
_mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color;
|
||||
_mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random;
|
||||
_mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow;
|
||||
_mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash;
|
||||
_mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random;
|
||||
_mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white;
|
||||
_mode[FX_MODE_COLORFUL] = &WS2812FX::mode_colorful;
|
||||
_mode[FX_MODE_TRAFFIC_LIGHT] = &WS2812FX::mode_traffic_light;
|
||||
_mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random;
|
||||
_mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color;
|
||||
_mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue;
|
||||
_mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random;
|
||||
_mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner;
|
||||
_mode[FX_MODE_COMET] = &WS2812FX::mode_comet;
|
||||
_mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks;
|
||||
_mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random;
|
||||
_mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas;
|
||||
_mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker;
|
||||
_mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient;
|
||||
_mode[FX_MODE_LOADING] = &WS2812FX::mode_loading;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_IN_OUT] = &WS2812FX::mode_dual_color_wipe_in_out;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_IN_IN] = &WS2812FX::mode_dual_color_wipe_in_in;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_OUT_OUT] = &WS2812FX::mode_dual_color_wipe_out_out;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_OUT_IN] = &WS2812FX::mode_dual_color_wipe_out_in;
|
||||
_mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus;
|
||||
_mode[FX_MODE_CUSTOM_CHASE] = &WS2812FX::mode_cc_standard;
|
||||
_mode[FX_MODE_CC_ON_RAINBOW] = &WS2812FX::mode_cc_rainbow;
|
||||
_mode[FX_MODE_CC_ON_RAINBOW_CYCLE] = &WS2812FX::mode_cc_cycle;
|
||||
_mode[FX_MODE_CC_BLINK] = &WS2812FX::mode_cc_blink;
|
||||
_mode[FX_MODE_CC_RANDOM] = &WS2812FX::mode_cc_random;
|
||||
|
||||
_mode_index = DEFAULT_MODE;
|
||||
_speed = DEFAULT_SPEED;
|
||||
_brightness = DEFAULT_BRIGHTNESS;
|
||||
_running = false;
|
||||
_led_count = n;
|
||||
_mode_last_call_time = 0;
|
||||
_mode_delay = 0;
|
||||
_color = DEFAULT_COLOR;
|
||||
_mode_color = DEFAULT_COLOR;
|
||||
_color_sec = 0;
|
||||
_mode_var1 = 0;
|
||||
_cc_fs = true;
|
||||
_cc_fe = false;
|
||||
_cc_is = 0;
|
||||
_cc_i1 = 0;
|
||||
_cc_i2 = n-1;
|
||||
_cc_num1 = 5;
|
||||
_cc_num2 = 5;
|
||||
_ccStep = 1;
|
||||
_counter_mode_call = 0;
|
||||
_counter_mode_step = 0;
|
||||
_counter_ccStep = 0;
|
||||
_fastStandard = false;
|
||||
_reverseMode = false;
|
||||
_locked = new bool[n];
|
||||
_cronixieDigits = new byte[6];
|
||||
}
|
||||
|
||||
void
|
||||
show(void),
|
||||
setPixelColor(uint16_t i, byte r, byte g, byte b),
|
||||
setPixelColor(uint16_t i, byte r, byte g, byte b, byte w),
|
||||
init(void),
|
||||
service(void),
|
||||
start(void),
|
||||
stop(void),
|
||||
setMode(byte m),
|
||||
setCustomChase(byte i1, byte i2, byte is, byte np, byte ns, byte stp, bool fs, bool fe),
|
||||
setCCIndex1(byte i1),
|
||||
setCCIndex2(byte i2),
|
||||
setCCStart(byte is),
|
||||
setCCNum1(byte np),
|
||||
setCCNum2(byte ns),
|
||||
setCCStep(byte stp),
|
||||
setCCFS(bool fs),
|
||||
setCCFE(bool fe),
|
||||
setSpeed(byte s),
|
||||
setIntensity(byte in),
|
||||
increaseSpeed(byte s),
|
||||
decreaseSpeed(byte s),
|
||||
setColor(byte r, byte g, byte b),
|
||||
setColor(byte r, byte g, byte b, byte w),
|
||||
setColor(uint32_t c),
|
||||
setSecondaryColor(byte r, byte g, byte b),
|
||||
setSecondaryColor(byte r, byte g, byte b, byte w),
|
||||
setSecondaryColor(uint32_t c),
|
||||
setBrightness(byte b),
|
||||
increaseBrightness(byte s),
|
||||
decreaseBrightness(byte s),
|
||||
setReverseMode(bool b),
|
||||
driverModeCronixie(bool b),
|
||||
setCronixieDigits(byte* d),
|
||||
setCronixieBacklight(bool b),
|
||||
setIndividual(int i),
|
||||
setIndividual(int i, uint32_t col),
|
||||
setRange(int i, int i2),
|
||||
setRange(int i, int i2, uint32_t col),
|
||||
lock(int i),
|
||||
lockRange(int i, int i2),
|
||||
lockAll(void),
|
||||
unlock(int i),
|
||||
unlockRange(int i, int i2),
|
||||
unlockAll(void),
|
||||
setFastUpdateMode(bool b),
|
||||
trigger(void),
|
||||
setLedCount(uint16_t i),
|
||||
setFade(int sp);
|
||||
|
||||
bool
|
||||
isRunning(void),
|
||||
isLocked(int i);
|
||||
|
||||
byte
|
||||
get_random_wheel_index(byte),
|
||||
getMode(void),
|
||||
getSpeed(void),
|
||||
getIntensity(void),
|
||||
getBrightness(void),
|
||||
getModeCount(void);
|
||||
|
||||
uint32_t
|
||||
color_wheel(byte),
|
||||
getColor(void);
|
||||
|
||||
double
|
||||
getPowerEstimate(byte leds, uint32_t c, byte b),
|
||||
getSafePowerMultiplier(double safeMilliAmps, byte leds, uint32_t c, byte b);
|
||||
|
||||
private:
|
||||
|
||||
void
|
||||
begin(void),
|
||||
clear(void),
|
||||
setPixelColor(uint16_t i, uint32_t c),
|
||||
setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w),
|
||||
dofade(void),
|
||||
strip_off(void),
|
||||
strip_off_respectLock(void),
|
||||
mode_static(void),
|
||||
mode_blink(void),
|
||||
mode_color_wipe(void),
|
||||
mode_color_wipe_random(void),
|
||||
mode_random_color(void),
|
||||
mode_easter(void),
|
||||
mode_dynamic(void),
|
||||
mode_breath(void),
|
||||
mode_fade(void),
|
||||
mode_scan(void),
|
||||
mode_dual_scan(void),
|
||||
mode_theater_chase(void),
|
||||
mode_theater_chase_rainbow(void),
|
||||
mode_rainbow(void),
|
||||
mode_rainbow_cycle(void),
|
||||
mode_running_lights(void),
|
||||
mode_twinkle(void),
|
||||
mode_twinkle_random(void),
|
||||
mode_twinkle_fade(void),
|
||||
mode_twinkle_fade_random(void),
|
||||
mode_sparkle(void),
|
||||
mode_flash_sparkle(void),
|
||||
mode_hyper_sparkle(void),
|
||||
mode_strobe(void),
|
||||
mode_strobe_rainbow(void),
|
||||
mode_multi_strobe(void),
|
||||
mode_blink_rainbow(void),
|
||||
mode_android(void),
|
||||
mode_chase_color(void),
|
||||
mode_chase_random(void),
|
||||
mode_chase_rainbow(void),
|
||||
mode_chase_flash(void),
|
||||
mode_chase_flash_random(void),
|
||||
mode_chase_rainbow_white(void),
|
||||
mode_colorful(void),
|
||||
mode_colorful_internal(uint32_t*),
|
||||
mode_traffic_light(void),
|
||||
mode_color_sweep_random(void),
|
||||
mode_running_color(void),
|
||||
mode_running_red_blue(void),
|
||||
mode_running_random(void),
|
||||
mode_larson_scanner(void),
|
||||
mode_comet(void),
|
||||
mode_fireworks(void),
|
||||
mode_fireworks_random(void),
|
||||
mode_merry_christmas(void),
|
||||
mode_fire_flicker(void),
|
||||
mode_gradient(void),
|
||||
mode_loading(void),
|
||||
mode_dual_color_wipe_in_out(void),
|
||||
mode_dual_color_wipe_in_in(void),
|
||||
mode_dual_color_wipe_out_out(void),
|
||||
mode_dual_color_wipe_out_in(void),
|
||||
mode_circus_combustus(void),
|
||||
mode_cc_core(void),
|
||||
mode_cc_standard(void),
|
||||
mode_cc_rainbow(void),
|
||||
mode_cc_cycle(void),
|
||||
mode_cc_blink(void),
|
||||
mode_cc_random(void);
|
||||
|
||||
bool
|
||||
_triggered,
|
||||
_fastStandard,
|
||||
_reverseMode,
|
||||
_cronixieMode,
|
||||
_cronixieBacklightEnabled,
|
||||
_cc_fs,
|
||||
_cc_fe,
|
||||
_running;
|
||||
|
||||
bool*
|
||||
_locked;
|
||||
|
||||
byte
|
||||
minval(byte v, byte w),
|
||||
maxval(byte v, byte w),
|
||||
_mode_index,
|
||||
_speed,
|
||||
_intensity,
|
||||
_cc_i1,
|
||||
_cc_i2,
|
||||
_cc_is,
|
||||
_cc_num1,
|
||||
_cc_num2,
|
||||
_ccStep,
|
||||
_brightness;
|
||||
|
||||
byte*
|
||||
_cronixieDigits;
|
||||
|
||||
uint16_t
|
||||
_led_count;
|
||||
|
||||
uint32_t
|
||||
getPixelColor(uint16_t i),
|
||||
_color,
|
||||
_color_sec,
|
||||
_counter_mode_call,
|
||||
_counter_mode_step,
|
||||
_counter_ccStep,
|
||||
_mode_var1,
|
||||
_mode_color,
|
||||
_mode_delay;
|
||||
|
||||
double
|
||||
_cronixieSecMultiplier;
|
||||
|
||||
unsigned long
|
||||
_mode_last_call_time;
|
||||
|
||||
mode_ptr
|
||||
_mode[MODE_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
124
wled00/__vm/.wled00.vsarduino.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Editor: https://www.visualmicro.com/
|
||||
This file is for intellisense purpose only.
|
||||
Visual micro (and the arduino ide) ignore this code during compilation. This code is automatically maintained by visualmicro, manual changes to this file will be overwritten
|
||||
The contents of the _vm sub folder can be deleted prior to publishing a project
|
||||
All non-arduino files created by visual micro and all visual studio project or solution files can be freely deleted and are not required to compile a sketch (do not delete your own code!).
|
||||
Note: debugger breakpoints are stored in '.sln' or '.asln' files, knowledge of last uploaded breakpoints is stored in the upload.vmps.xml file. Both files are required to continue a previous debug session without needing to compile and upload again
|
||||
|
||||
Hardware: ESP32 Dev Module, Platform=esp32, Package=esp32
|
||||
*/
|
||||
|
||||
#if defined(_VMICRO_INTELLISENSE)
|
||||
|
||||
#ifndef _VSARDUINO_H_
|
||||
#define _VSARDUINO_H_
|
||||
#define __ESP32_esp32__
|
||||
#define __ESP32_ESP32__
|
||||
#define ESP_PLATFORM
|
||||
#define HAVE_CONFIG_H
|
||||
#define GCC_NOT_5_2_0 0
|
||||
#define WITH_POSIX
|
||||
#define F_CPU 240000000L
|
||||
#define ARDUINO 108011
|
||||
#define ARDUINO_ESP32_DEV
|
||||
#define ARDUINO_ARCH_ESP32
|
||||
#define ESP32
|
||||
#define CORE_DEBUG_LEVEL 0
|
||||
#define __cplusplus 201103L
|
||||
|
||||
#define _Pragma(x)
|
||||
#undef __cplusplus
|
||||
#define __cplusplus 201103L
|
||||
|
||||
#define __STDC__
|
||||
#define __ARM__
|
||||
#define __arm__
|
||||
#define __inline__
|
||||
#define __asm__(...)
|
||||
#define __extension__
|
||||
#define __ATTR_PURE__
|
||||
#define __ATTR_CONST__
|
||||
#define __volatile__
|
||||
|
||||
#define __ASM
|
||||
#define __INLINE
|
||||
#define __attribute__(noinline)
|
||||
|
||||
//#define _STD_BEGIN
|
||||
//#define EMIT
|
||||
#define WARNING
|
||||
#define _Lockit
|
||||
#define __CLR_OR_THIS_CALL
|
||||
#define C4005
|
||||
#define _NEW
|
||||
|
||||
typedef bool _Bool;
|
||||
typedef int _read;
|
||||
typedef int _seek;
|
||||
typedef int _write;
|
||||
typedef int _close;
|
||||
typedef int __cleanup;
|
||||
|
||||
//#define inline
|
||||
|
||||
#define __builtin_clz
|
||||
#define __builtin_clzl
|
||||
#define __builtin_clzll
|
||||
#define __builtin_labs
|
||||
#define __builtin_va_list
|
||||
typedef int __gnuc_va_list;
|
||||
|
||||
#define __ATOMIC_ACQ_REL
|
||||
|
||||
#define __CHAR_BIT__
|
||||
#define _EXFUN()
|
||||
|
||||
typedef unsigned char byte;
|
||||
extern "C" void __cxa_pure_virtual() {;}
|
||||
|
||||
typedef long __INTPTR_TYPE__ ;
|
||||
typedef long __UINTPTR_TYPE__ ;
|
||||
typedef long __SIZE_TYPE__ ;
|
||||
typedef long __PTRDIFF_TYPE__;
|
||||
|
||||
typedef long pthread_t;
|
||||
typedef long pthread_key_t;
|
||||
typedef long pthread_once_t;
|
||||
typedef long pthread_mutex_t;
|
||||
typedef long pthread_mutex_t;
|
||||
typedef long pthread_cond_t;
|
||||
|
||||
|
||||
|
||||
#include "arduino.h"
|
||||
#include <pins_arduino.h>
|
||||
|
||||
#define interrupts() sei()
|
||||
#define noInterrupts() cli()
|
||||
|
||||
#define ESP_LOGI(tag, ...)
|
||||
|
||||
#include "wled00.ino"
|
||||
#include "wled01_eeprom.ino"
|
||||
#include "wled02_xml.ino"
|
||||
#include "wled03_set.ino"
|
||||
#include "wled04_file.ino"
|
||||
#include "wled05_init.ino"
|
||||
#include "wled06_usermod.ino"
|
||||
#include "wled07_notify.ino"
|
||||
#include "wled08_led.ino"
|
||||
#include "wled09_button.ino"
|
||||
#include "wled10_ntp.ino"
|
||||
#include "wled11_ol.ino"
|
||||
#include "wled12_alexa.ino"
|
||||
#include "wled13_cronixie.ino"
|
||||
#include "wled14_colors.ino"
|
||||
#include "wled15_hue.ino"
|
||||
#include "wled16_blynk.ino"
|
||||
#include "wled17_mqtt.ino"
|
||||
#include "wled18_server.ino"
|
||||
#include "wled19_json.ino"
|
||||
#include "wled20_ir.ino"
|
||||
#endif
|
||||
#endif
|