I heard a lot about “if you want to control LEDs, use WLED“. I never had a need to control LEDs (the strip type), but today I had some spare time and I tested it with a spare ESP8266 and a single WS2812B LED. WLED is not really made for single LEDs, but as a proof-of-concept it’ll have to do.
Can’t say much here though: the install went as expected, connecting to the access point it created was straightforward, setting up my WiFi credentials worked, and controlling the single LED via web interface or Android app was as easy as it can get. This was one of the easiest installs of any IoT thing I ever had.
Now I do have to get me some LED strips to play a bit more with it…
Update: Ok, got myself a 60 LED WS2812B strip. And WLED effects look much better for obvious reasons. And you can split the 60 LEDs into segments and set their respective colors via curl easily:
Above sets the color of the 3rd segment to blue (assuming the effect is “Solid”). That’s way better and easier than any other API I’ve seen for WiFi connected lights.
Today via reddit I found a neat little utility I never heard of: uhubctl. It can turn off/on/toggle power on USB ports. And it works perfectly on my old 7 port USB 3 hub (look for the 1050:0120 Yubikey on hub 2-4.1 port 1):
❯ uhubctl
Current status for hub 3-4.1 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 02a0 power 5gbps Rx.Detect
Port 2: 02a0 power 5gbps Rx.Detect
Port 3: 02a0 power 5gbps Rx.Detect
Port 4: 02a0 power 5gbps Rx.Detect
Current status for hub 3-4 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 0263 power 5gbps U3 enable connect [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 2: 02a0 power 5gbps Rx.Detect
Port 3: 02a0 power 5gbps Rx.Detect
Port 4: 02a0 power 5gbps Rx.Detect
Current status for hub 2-4.1 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0103 power enable connect [1050:0120 Yubico Security Key by Yubico]
Port 2: 0100 power
Port 3: 0100 power
Port 4: 0100 power
Current status for hub 2-4 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0503 power highspeed enable connect [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 2: 0100 power
Port 3: 0100 power
Port 4: 0103 power enable connect [1852:7022 FiiO DigiHug USB Audio]
❯ uhubctl -a off -l 2-4.1 -p 1
Current status for hub 3-4.1 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 02a0 power 5gbps Rx.Detect
Sent power off request
New status for hub 3-4.1 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 0080 off
Current status for hub 2-4.1 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0103 power enable connect [1050:0120 Yubico Security Key by Yubico]
Sent power off request
New status for hub 2-4.1 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0000 off
❯ uhubctl
Current status for hub 3-4.1 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 0080 off
Port 2: 02a0 power 5gbps Rx.Detect
Port 3: 02a0 power 5gbps Rx.Detect
Port 4: 02a0 power 5gbps Rx.Detect
Current status for hub 3-4 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 0263 power 5gbps U3 enable connect [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 2: 02a0 power 5gbps Rx.Detect
Port 3: 02a0 power 5gbps Rx.Detect
Port 4: 02a0 power 5gbps Rx.Detect
Current status for hub 2-4.1 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0000 off
Port 2: 0100 power
Port 3: 0100 power
Port 4: 0100 power
Current status for hub 2-4 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0503 power highspeed enable connect [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 2: 0100 power
Port 3: 0100 power
Port 4: 0103 power enable connect [1852:7022 FiiO DigiHug USB Audio]
❯ uhubctl -a on -l 2-4.1 -p 1
Current status for hub 3-4.1 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 0080 off
Sent power on request
New status for hub 3-4.1 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 02a0 power 5gbps Rx.Detect
Current status for hub 2-4.1 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0000 off
Sent power on request
New status for hub 2-4.1 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0101 power connect [1050:0120]
❯ uhubctl
Current status for hub 3-4.1 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 02a0 power 5gbps Rx.Detect
Port 2: 02a0 power 5gbps Rx.Detect
Port 3: 02a0 power 5gbps Rx.Detect
Port 4: 02a0 power 5gbps Rx.Detect
Current status for hub 3-4 [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 1: 0263 power 5gbps U3 enable connect [2109:0812 VIA Labs, Inc. USB3.0 Hub, USB 3.00, 4 ports, ppps]
Port 2: 02a0 power 5gbps Rx.Detect
Port 3: 02a0 power 5gbps Rx.Detect
Port 4: 02a0 power 5gbps Rx.Detect
Current status for hub 2-4.1 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0103 power enable connect [1050:0120 Yubico Security Key by Yubico]
Port 2: 0100 power
Port 3: 0100 power
Port 4: 0100 power
Current status for hub 2-4 [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 1: 0503 power highspeed enable connect [2109:2812 VIA Labs, Inc. USB2.0 Hub, USB 2.10, 4 ports, ppps]
Port 2: 0100 power
Port 3: 0100 power
Port 4: 0103 power enable connect [1852:7022 FiiO DigiHug USB Audio]
Neat as now I can power control all kind of USB devices and there’s plenty of stuff which uses USB as power source.
Deno can use shared libraries which follow the normal C convention, thus allowing Deno programs to call C functions. Since there’s no way to create raw Ethernet packets within Deno and I found no library doing this, I think I’ll have to create it myself similar to what I did with Dart and its FFI.
But first I wanted to know what the overhead of calling a C function in a shared library is as this GitHub issue seems to make it very slow.
Time to measure! So I created a simple C function to add up bytes in an array:
int sum(const uint8_t *p, int count) {
int res=0;
for (int i=0; i<count; ++i) {
res += p[i];
}
return res;
}
and call this with variable amounts of count, from 1 to 4096. From Deno call it:
for (let size = 1 ; size < buf.length; size *= 2) {
start = performance.now();
for (let i = 0; i < 1_000_000; ++i) {
result = dylib.symbols.sum(buf, size);
}
end = performance.now();
console.log(`Time used for ${size} bytes: ${end-start}ns`);
}
performance.now() returns a time stamp in ms, thus since the test call is done 1M times, the result shows the time in ns:
Bytes
AMD GX-420CA
AMD Ryzen 5 3400GE
RK3328@1.3GHz
Khadas VIM3L S905D3@1.9GHz
AWS C6G
4
38
12
1274
864
228
8
56
18
1342
902
232
16
90
34
1464
982
252
32
174
64
1698
1134
292
64
310
140
2170
1436
386
128
584
268
3120
2042
556
256
1130
544
4998
3252
904
512
2224
1022
8764
5678
1620
1024
4410
2048
16304
10520
3014
2048
8800
4072
31378
20200
5808
4096
17554
8076
61690
39598
11374
Overhead
23
14
1213
830
212
Calling FFI from Deno with increasing amount of work done inside the FFI, Deno version 1.29.3 (ARM: 1.29.4)
Linear regression shows 23ns and 14ns overhead (extrapolate for size=0) for the x86_64 CPUs. Note how nicely the time increases with larger payloads. The ARM CPUs start to show linear increases only at about 128 bytes, and their overhead is quite a lot higher at 830ns and 212ns.
Given that one 1500 byte Ethernet frame at 1 GBit/s takes 12μs, the overhead for the slower AMD CPU is only 0.2%, this is very acceptable. Even for more typical frames of 500 byte (128 pixel, 3 colors, plus a bit of overhead), the overhead is only 0.6%.
The ARM CPUs have significantly more overhead (7% for a 1500 byte frame for the S905D3, and 20% for a 500 byte frame). Even using a server type ARM CPU does not improve it by much.
Appendix
Deno version: 1.29.3 for x86_64, and 1.29.4 for ARMv8 compiled via
I am using step-ca for over 2 years now on a small little NanoPi R2S (1GB RAM). And I am monitoring it too, e.g. for the last 6 months memory is very stable and more importantly: not increasing over time. Memory leaks are real, but not on this baby:
At the very end it’s changing, and it’s changing very suddenly too. Here the last 7 days:
What did not work:
Reset the server
Reboot the server
Actually it worked for less than a minute. By then memory exhaustion happened and the server was busy swapping. Connecting via ssh became a gamble at this point.
After a reboot there’s about 1min time to stop step-ca. A simple kill won’t do because systemd would restart it, so a
systemctl stop step-ca
did the job. Just have to be fast enough to execute it.
What happened?
It seems that the internal DB (BadgerV2), which by default is in ~/.step/db/ increased over time to much that its management consumed rather suddenly so much memory that swapping happened. One parameter I did not use (left it empty):
badgerFileLoadingMode [optional]: can be set to FileIO (instead of the default MemoryMap) to avoid memory-mapping log files. This can be useful in environments with low RAM. Make sure to use badgerV2 as the database type if using this option.
MemoryMap: default.
FileIO: This can be useful in environments with low RAM
Needless to say, the default works fine as long as the DB does not get too big. In my case it was 4.7GB in size:
I find it impressive that the default of MemoryMapped worked that well on a 1 GB RAM machine, but I guess in the last days it stopped working.
The Fix
Starting step-ca manually worked with no error messages, but it used more and more memory. I downgraded from v0.23.0 to 0.17.2 as I upgraded some week ago, but it made zero difference. Finding the 4 GB db solved the problem: since the config and all secret keys/certificates are not in the DB, I tried to simply wipe it out, and that worked as expected: step-ca created a new DB. When started it used about 10% memory, and then even less. Back to normal.
Lesson I learned: watch your monitoring. This behavior started on 15th and it took me 3 days to realize.
Am Freitag vor 2 Tagen ist ein langjähriger Freund von mir gestorben. Er war etwa so alt wie ich, und er schien kerngesund zu sein vor ein paar Jahren als wir uns zuletzt getroffen haben. Er hatte eine neue Lebensgefährtin gefunden und sie planten im nächsten Jahr zu heiraten. Beim letzten Telefongespräch hörte er sich sehr glücklich an und ich hätte mich sehr gefreut beide beim nächsten Besuch in Deutschland zu treffen.
Daraus wird aber leider nichts mehr.
Man kann die Vergangenheit nicht ändern, aber in der Zukunft werde ich weniger Sachen auf das nächste Jahr verschieben. Manchmal gibt es eben kein “nächstes Jahr”.
2 years ago I bought a tablet (Huion HS611) for playing Osu! but I quickly found out that I suck at it. Drawing is not my thing either, so it was mostly unused.
But then recently my Microsoft Sculpt Mouse broke (single click made double clicks). I have a spare mouse which is very “un-ergonomic”. So I needed another replacement, and I tested again the tablet, but this time as a mouse-replacement.
And it’s better than I expected!
Scrolling is very easy (like on a phone).
Single-click is super-easy although click-and-drag does not work at all as it’s used for scrolling.
Double-click and right-mouse-button-clicks are hard: the pen pointer moves a lot more than when using a mouse.
Having the pen in your hand means that when you type, you either drop the pen or you type with a pen between your fingers.
The one problem I had was that the Huion driver puts Windows into “Tablet mode”, which is generally correct. However it also means Windows likes to pop up a soft keyboard. It should not as I have a USB keyboard connected. It’s annoying as heck then it happens. Luckily the fix is simple.
No more soft keyboard pop-up
Run services.msc, find the Touch Keyboard and Handwriting Panel Service and simply disable it.
Found this Wikipedia article about BASIC benchmarks and it had some run times for some old computers I used before. E.g. benchmark 7 took 21.1s on a BBC Micro which was particularly fast. A C64 took 47.5s
How long does a current computer take for this kind of work?
I got no BASIC, but JavaScript is kind’a similar: it’s often the first language to learn programming. So let’s see how long that takes (after translating the BASIC program into JavaScript):
function doNothing() {
return;
}
function bench7() {
let k = 0;
let m = [];
do {
++k;
let a = k / 2 * 3 + 4 - 5;
doNothing();
for (let l = 0; l < 5; ++l) {
m[l] = a;
}
} while (k < 1000);
}
function manyBench(n) {
console.log("S");
for (let i=0; i<n; ++i) {
bench7();
}
console.log("E");
}
manyBench(500000);
Running this took not that long:
❯ time node benchmark7.js
S
E
node benchmark7.js 2.82s user 0.02s system 99% cpu 2.845 total
That’s for 500,000 times though, so each benchmark run takes about 0.056ms on my low-end PC (Ryzen 5 Pro 3400GE). That’s over 3.7M times faster.
And before anyone mentions it: yes, any modern compiler will optimize the whole benchmark away since no useful output or calculation is done. I am not sure how much Node.js (resp. the V8 engine) will remove. Making the code less do-nothing-like and taking the number of loops from the command line did not increase the run time significantly beside what I would have expected from the additional code, so I concluded that the code is executed as-is and parts have not been optimized away.
It’s still September, but winter will come soon. I learned about Software Defined Radio years ago, but the equipment was very expensive or limited. The software ecosystem wasn’t that large either.
However that has changed in the meantime: an Airspy is US$169 and the SpyVerter $49 and that combo can scan anything from DC to 1.8GHz.
First order was watching the spectrum at various wavelength via SDR#:
Scanning 433MHz band
As you can see it detects nicely when I pushed a button on the 433.92MHz remote control. Interestingly there’s a slight 3kHz miss-tuning for the small remote compared to the RF bridge:
Red line: 433.92MHz. Lower signal: RF Bridge, upper signal: remote control
And I can listen to FM radio (very poor quality since the antenna I have is for 433MHz band):
FM Radio
To use any other bands beside 433MHz I’d need different or adjustable antennas. Something for later to worry about.
Decoding the RF Remote Control
Recognizing and decoding digital signals is surprisingly easy with the right tools. rtl_433 can decode a lot of standard devices, so it was my first attempt. Compiling was a bit more complex than I though due to dependencies. It was well enough documented though. After that’s done, time to decode some signals!
This shows output like this for every button press and usually several times repeated:
Analyzing pulses...
Total count: 25, width: 290297.52 ms (72574379 S)
Pulse width distribution:
[ 0] count: 1, width: 289230564 us [289230564;289230564] (72307641 S)
[ 1] count: 16, width: 11380 us [11372;11456] (2845 S)
[ 2] count: 8, width: 33640 us [33636;33644] (8410 S)
Gap width distribution:
[ 0] count: 9, width: 11708 us [11684;11728] (2927 S)
[ 1] count: 15, width: 34020 us [33880;34284] (8505 S)
Pulse period distribution:
[ 0] count: 1, width: 289242292 us [289242292;289242292] (72310573 S)
[ 1] count: 23, width: 45380 us [45256;45660] (11345 S)
Pulse timing distribution:
[ 0] count: 1, width: 289230564 us [289230564;289230564] (72307641 S)
[ 1] count: 25, width: 11496 us [11372;11728] (2874 S)
[ 2] count: 23, width: 33888 us [33636;34284] (8472 S)
[ 3] count: 1, width: 100004 us [100004;100004] (25001 S)
Level estimates [high, low]: 126, -1
RSSI: -42.3 dB SNR: 42.0 dB Noise: -84.3 dB
Frequency offsets [F1, F2]: 121, 0 (+0.5 kHz, +0.0 kHz)
Guessing modulation: Pulse Width Modulation with sync/delimiter
view at https://triq.org/pdv/#AAB104FFFF2CE88460FFFF819292929292A19292A1A1A1A1929292A1A192929292A1929355
Attempting demodulation... short_width: 11380, long_width: 33640, reset_limit: 34288, sync_width: 289230560
Use a flex decoder with -X 'n=name,m=OOK_PWM,s=11380,l=33640,r=34288,g=0,t=0,y=289230560'
pulse_slicer_pwm(): Analyzer Device
bitbuffer:: Number of rows: 1
[00] {24} fb 0e 7b : 11111011 00001110 01111011
Note the line with the flex decoder: those numbers vary slightly. Take the average for s, for l and r. Use the most common values for g and y. Use t to add some margin of timing error. I have 2 RF devices: a small remote control and a RF-Wifi bridge. Both can send the same signals, but their timing is slightly off:
Remote: s=13378±5, l=33638±10, r=34929±10
Bridge: s=11635±40, l=34198±10, r=34768±10
So I took the average, added some slack and that worked for both devices: