tag:blogger.com,1999:blog-77760214599985324942024-03-13T02:32:47.324-07:00The Little Engineer That CouldAs a one man game studio (an INDIEvidual) Bram Stolk develops games. This is his development diary.Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.comBlogger166125tag:blogger.com,1999:blog-7776021459998532494.post-6820570830861287022023-09-09T12:28:00.004-07:002023-09-30T19:06:31.545-07:00Vulkan Compute<div class="separator" style="clear: both;"><a href="https://i.extremetech.com/imagery/content-types/01QTr9nmIrb1SOyVxzNNWvH/hero-image.fill.size_1200x675.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="450" data-original-width="800" src="https://i.extremetech.com/imagery/content-types/01QTr9nmIrb1SOyVxzNNWvH/hero-image.fill.size_1200x675.jpg"/></a></div>
<P ALIGN="justify">
So, my <a href="http://thelittleengineerthatcould.blogspot.com/2021/01/practica-boxel.html">Photon Mapping experiments</a> led me from <b>CUDA</b> to <b>OpenCL</b> (for better compatibility) and now to <b>Vulkan</b> for even better compatiblity.
OpenCL is just not cutting it anymore: abandoned by Apple, ignored by AMD.
The latter I found out when I tried to use OpenCL on a mobile Ryzen iGPU under Linux: no go!
</P>
<P ALIGN="justify">
So Vulkan it is.
I have always found Vulkan to be intimidating.
It is just too much, before you will ever see a single triangle on your screen.
I am hopeful that Vulkan Compute is less cumbersome, and it seems to be that way.
</P>
<P ALIGN="justify">
You still needs heaps and heaps of configuration and setup code, though.
And I am slowly making my way through that.
You can follow my progress at <A HREF="https://github.com/stolk/MinimalVulkanCompute/">MinimalVulkanCompute</A> github.
</P>
<P ALIGN="justify">
Some other sources for inspiration are <A HREF="https://github.com/SaschaWillems/Vulkan/blob/master/examples/computeheadless/computeheadless.cpp">Sascha Willems' example</A> and <A HREF="https://gist.github.com/sheredom/523f02bbad2ae397d7ed255f3f3b5a7f">Neil Henning's example</A>
</P>
<P ALIGN="justify">
Vulkan uses SPIR-V modules to represent the compute kernels.
So I need to port my OpenCL or CUDA code to this.
I think I can just transpile my OpenCL code into SPIR-V using Google's <a href="https://github.com/google/clspv/">clspv project</a>.
</P>
<P ALIGN="justify">
After building clspv it appears that it ingests my OpenCL code pretty well, as it manages to create SPIR-V output.
So far so good.
I still need to execute it in my Vk code.
I wonder how much performance is lost by the intermediate step, compared to a native OpenCL driver?
</P>
<P ALIGN="justify">
Next order of business is to figure out if I should create staging buffers.
For an iGPU, all memory is the same.
But for a dGPU, I have a lot of options for which type of memory to use.
For instance, using my RX580 Radeon dGPU, I see:
</P>
<FONT SIZE=2>
<PRE>
$ ./minimal_vulkan_compute
Found 3 physical devices.
8086:4680 iGPU Intel(R) UHD Graphics 770 (ADL-S GT1)
1002:67df dGPU AMD Radeon RX 580 Series (RADV POLARIS10)
10005:0000 CPU llvmpipe (LLVM 15.0.7, 256 bits)
7 mem types. 2 mem heaps.
4096 MiB of local memory [ device-local ]
4096 MiB of local memory [ device-local ]
15908 MiB of non-local memory [ host-visible host-coherent ]
4096 MiB of local memory [ device-local host-visible host-coherent ]
4096 MiB of local memory [ device-local host-visible host-coherent ]
15908 MiB of non-local memory [ host-visible host-coherent host-cached ]
15908 MiB of non-local memory [ host-visible host-coherent host-cached ]
</PRE>
</FONT>
<H2>UPDATE</H2>
<P ALIGN="justify">
I have the vulkan port finally working as it should.
Some things that tripped me up: A Vulkan kernel gets the work group size from the SPIRV. Whereas an OpenCL kernel can just set it in the clEnqueueNDRangeKernel() call, at client side.
This makes the clspv route a little tricky: we need to spec the workgroup size in the CL kernel source, using __attribute__((reqd_work_group_size(x, y, z)))
</P>
<P ALIGN="justify">
The end result is that the CL -> clspv -> SPIRV -> Vulkan overhead takes quite a bit of performance away.
The overhead is tolerable on nvidia RTX, but it is too much on Intel:
</P>
<FONT SIZE=2>
<PRE>
NVIDIA GeForce RTX 3060 Laptop GPU NVIDIA Corporation with [30 units]
OPENCL:
rayt: 2953 µs
boun: 2989 µs
binp: 1458 µs
CLSPV+VULKAN:
rayt: 3543 μs
boun: 3586 μs
binp: 1224 μs
</PRE>
</FONT>
<FONT SIZE=2>
<PRE>
Intel(R) UHD Graphics 770 (ADL-S GT1)
OPENCL:
rayt: 22017 µs
boun: 20927 µs
binp: 7310 µs
CLSPV+VULKAN:
rayt: 44635 μs
boun: 40133 μs
binp: 8490 μs
</PRE>
</FONT>
<H2>CONCLUSION</H2>
<P ALIGN="justify">
Depending on the platform, my compute time goes up between +20% and +100% when using transpiled OpenCL kernels via clspv. I should also mention that I have found the performance difference between CUDA and OpenCL insignificant.
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com3tag:blogger.com,1999:blog-7776021459998532494.post-26003181472326331452023-06-07T12:15:00.007-07:002023-06-08T11:37:08.851-07:00Frames per Joule.<P ALIGN="justify">
We have fallen for the folly of maximum GPU performance.
It is the age of <A HREF="https://www.chillblast.com/blog/what-power-supply-do-you-need-for-the-nvidia-rtx-4090">450 Watt</A> GPUs. Why is that?
</P>
<P ALIGN="justify">
There is absolutely no need to have 450 Watt GPUs.
The sole reason they use that much, is for a few additional FPS <B>in the benchmarks</B>.
For real-world use, that 450 Watt is useless, as I have come to conclude after running an experiment.
</P>
<P ALIGN="justify">
Traditionally, I have always used NVIDIA GPUs in my Linux boxes, for stability and performance.
But today, I am running an (elderly) AMD RX580 in my main rig.
NVIDIA on Linux does not give you much control over clock speeds and voltages, but <A HREF="https://gitlab.com/corectrl/corectrl">CoreCtrl</A> let's me adjust the clocks for the RX580.
</P>
<P ALIGN="justify">
I already knew that for the last few percent of performance, you need a heap more wattage.
This is because Wattage increases linearly with clock speed, but quadratically to the Voltage.
Increasing Voltage comes at a huge cost. Let's quantify that cost.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAWtpNOc8sQiGLtNgXGdt3jKGcSovVJKsYhWr7v4RpRnpdjIiMZ-1wYuoU5ZFxqyElrCP8Zr5dtjiJgASpPsEWXyaDsH0Rt1jKtb-Dr2gJsbz8EKndGmSJkGeBPJQy0NJEfOThXgSJN-5z6AD3hSVzt-tK7Nlu-eOkUYzTqrLmSpkakaEKodRMeEVH5w/s1840/voltage.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1620" data-original-width="1840" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAWtpNOc8sQiGLtNgXGdt3jKGcSovVJKsYhWr7v4RpRnpdjIiMZ-1wYuoU5ZFxqyElrCP8Zr5dtjiJgASpPsEWXyaDsH0Rt1jKtb-Dr2gJsbz8EKndGmSJkGeBPJQy0NJEfOThXgSJN-5z6AD3hSVzt-tK7Nlu-eOkUYzTqrLmSpkakaEKodRMeEVH5w/s600/voltage.png"/></a></div>
<P ALIGN="justify">
I benchmarked <A HREF="https://twitter.com/BramStolk/status/1655290064317087744?s=20">my Photon Mapping engine</A> on two settings:
900Mhz GPU, 1000 MHz VRAM versus: 1360MHz GPU, 1750 MHz VRAM.
</P>
<P ALIGN="justify">
I then checked the FPS and the (reported!) Wattage. I guess for a more complete tests, measuring power consumption at the wall socket would have been better. Maybe another time.
</P>
<P ALIGN="justify">
So, with the higher clocks, we expect better performance of course. Did we get better performance?
</P>
<PRE>
Clocks FPS Volt Watt
900/1000 38 0.850 47
1360/1750 46 1.150 115
</PRE>
<P ALIGN="justify">
The result was even more extreme than I expected:
<B>For 145% more power consumption, I got to enjoy 21% more frames/s</B>.
</P>
<P ALIGN="justify">
Not only that. The high-clock setting came with a deafening fan noise, whereas I did not hear a thing at low Voltage.
</P>
<P ALIGN="justify">
Which now makes me ask the question:
Shouldn't those benchmarking youtube channels do their tests differently?
Why are we not measuring --deep breath-- frames per second per (joule per second) instead? (As Watt is defined as Joule/Second.)
</P>
<P ALIGN="justify">
We can of course simplify those units as frames per joule, as the time units cancel each other out.
</P>
<P ALIGN="justify">
Hot take: LTT, JayzTwoCents, GamersNexus should all be benchmarking GPUs at at lower Voltage/Clock setting.
I do not care if RTX inches out a Radeon by 4% more FPS at 450Watt. I want to know how they perform with a silent fan, and lowered voltage. Consumer Report tests a car at highway speeds, not on a race track with Nitrogen Oxide and a bolted on Supercharger. We should test GPUs more reasonably.
</P>
<P ALIGN="justify">
Can we please have test reports with Frames per Joule? Where is my FPJ at?
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAGxbuE3YxHdXSfDGtS7UU7OPPeeprI2NiBllRbUpJz6zmSb7Lv8pum5bgr8gjNuEfU2nsBX5nWxa_z_ZKCGvK9Q2XVL65_IU6gqf_kd099M7Phzl54Kto88y9cYrsiuAk1b_v8TyjjKC7vFc_BQ_1mPif6ul6pOOIsdGoLxj-koDOh7yWzdN-9hC1kg/s1440/brain.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1403" data-original-width="1440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAGxbuE3YxHdXSfDGtS7UU7OPPeeprI2NiBllRbUpJz6zmSb7Lv8pum5bgr8gjNuEfU2nsBX5nWxa_z_ZKCGvK9Q2XVL65_IU6gqf_kd099M7Phzl54Kto88y9cYrsiuAk1b_v8TyjjKC7vFc_BQ_1mPif6ul6pOOIsdGoLxj-koDOh7yWzdN-9hC1kg/s600/brain.png"/></a></div>
<P ALIGN="justify">
<B>UPDATE:</B> I can't believe I missed the stage-4 galaxy brain.
We can invert that unit to Joules/Frame instead!
</P>
<div class="separator" style="clear: both;"><a href="https://pbs.twimg.com/media/FyGwhcjacAElqMx?format=jpg&name=large" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="300" data-original-width="800" src="https://pbs.twimg.com/media/FyGwhcjacAElqMx?format=jpg&name=large"/></a></div>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-52142881007639390592023-06-02T16:23:00.002-07:002023-06-03T15:27:53.563-07:00The lacking state of rPi4 GPU support.<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWGI6ShpcHKPDZK1Z07xyyCdSqNke3YWtak6GJJxlgNWYmu1YlVu9TCRUAqjSrWjy8mA0RVpR2pSfB_MXA_wHQPKUZV4bmMptcJo7qVMMUpsVIzvCShtCgLBVuklGwQ6ghmWinPphcDL7-Br5bt326DrisiEoVJHcTk50k9-REODJMJsz-glxdX0Sn9Q/s500/Pi400_4__03484.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="357" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWGI6ShpcHKPDZK1Z07xyyCdSqNke3YWtak6GJJxlgNWYmu1YlVu9TCRUAqjSrWjy8mA0RVpR2pSfB_MXA_wHQPKUZV4bmMptcJo7qVMMUpsVIzvCShtCgLBVuklGwQ6ghmWinPphcDL7-Br5bt326DrisiEoVJHcTk50k9-REODJMJsz-glxdX0Sn9Q/s600/Pi400_4__03484.jpg"/></a></div>
<P ALIGN="justify">
Because I am a sucker for Linux SBCs, I got myself a
<A HREF="https://sipeed.com/licheepi4a/">Sipeed Lichee Pi 4A RISCV SBC.</A>
And remarkably, it can do OpenCL too! Which means I can try my Photon-Mapping
CL kernel on it.
</P>
<P ALIGN="justify">
Even though it can run OpenCL kernels, I did find that the OpenCL implementation is not the most stable one:
As soon as I try to fill a buffer with <A HREF="https://man.opencl.org/clEnqueueFillBuffer.html">clEnqueueFillBuffer()</A> it will <A HREF="https://stackoverflow.com/questions/76375746/clearing-an-opencl-buffer-using-an-imagination-img-gpu">crash</A>.
</P>
<P ALIGN="justify">
The performance of my kernel on this SBC was incredibly bad though: three orders of a magnitude slower than a desktop GPU. Which made me wonder what the performance would be on my Raspberry Pi 400.
</P>
<P ALIGN="justify">
Eben Upton <A HREF="https://www.raspberrypi.com/news/vulkan-update-version-1-2-conformance-for-raspberry-pi-4/">designed the VideoCore IV GPU</A> in the original rPi. So surely, the software support should be excellent.
Sadly, there is no OpenCL for the rPi4.
</P>
<P ALIGN="justify">
<A HREF="https://github.com/kpet/clvk">CLVK</A> to the rescue! This sofware will translate OpenCL kernels to Vulkan compute kernels.
Even though RaspberryPi OS would not work with it, Ubuntu 23.04 for rPi would, as it had a newer Mesa.
</P>
<P ALIGN="justify">
Which brings us to the next disappointment: even though there is a Vulkan driver for the rPi4, this driver lacks important Vulkan extensions. It cannot handle 16-bit floats, nor can it handle 8-bit ints.
</P>
<FONT SIZE=2>
<PRE>
unknown NIR ALU inst: vec1 16 div ssa_217 = b2f16! ssa_182
</PRE>
</FONT>
<P ALIGN="justify">
This leaves us with a rather lacking implementation.
Since I wrote my Photon Mapper for FP16, this experiment has to be shelved.
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-2608980239753637142023-04-26T10:36:00.006-07:002023-04-27T12:07:22.339-07:00Practical differences cuda / opencl<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVGGZvRyMhHrMdGAIrA2qAoDH9btZm_paGx3tAdy47AvswfdnSuF5GVdxvBXFX24eMQM6TRPyNgMn54jlcZU-kAGiL3jgVj43EigjgSkft90LrGV91Nw1HSGNGWRp6-Nd5KgEKfke71V7dBpg2syc-JIzRH3gjqZqf89y67yngybLGFvTDWgD4gI1WEg/s1024/opencl-og-twitter.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="512" data-original-width="1024" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVGGZvRyMhHrMdGAIrA2qAoDH9btZm_paGx3tAdy47AvswfdnSuF5GVdxvBXFX24eMQM6TRPyNgMn54jlcZU-kAGiL3jgVj43EigjgSkft90LrGV91Nw1HSGNGWRp6-Nd5KgEKfke71V7dBpg2syc-JIzRH3gjqZqf89y67yngybLGFvTDWgD4gI1WEg/s600/opencl-og-twitter.jpg"/></a></div>
<P ALIGN="justify">
Once again, I find myself porting CUDA code to OpenCL.
And I had to remind myself of the process, and the differences between the two.
Let's document, so future Bram will catch up quickly again.
</P>
<P ALIGN="justify">
The major difference is of course <B>compatibility</B>.
OpenCL is supported by Nvidia, Amd, Intel, etc.
CUDA is only supported by Nvidia.
It's the whole reason of this porting exercise.
</P>
<P ALIGN="justify">
<B>The CUDA-kernel can be pre-compiled by the developer using nvcc</B>, and then be shipped as a PTX file. The OpenCL-kernel typically ships as C-like source.
</P>
<P ALIGN="justify">
The function definition of a CUDA-kernel gets prefixed with <B>__kernel</B> whereas an OpenCL uses a <B>__global__</B> prefix.
</P>
<P ALIGN="justify">
A CUDA-kernel uses <B>blockIdx</B> and blockDim to determine which sub-part of the input data it is supposed to process. An OpenCL kernel uses <B>get_global_id()</B> instead.
</P>
<P ALIGN="justify">
Using 16 bit floating point arithmetic is as easy as <B>#include <cuda_fp16.h></B> and using __half. On OpenCL you need to check for an extension and add <B>#pragma OPENCL EXTENSION cl_khr_fp16 : enable</B>
</P>
<P ALIGN="justify">
In CUDA, constant input data is prefixed with <B>__constant__</B> which the host then sets with the cuMemcpyHtoDAsync() function after getting the symbol using the cuModuleGetGlobal() function. In OpenCL if the constant input data is large, you prefix it with <B>__global__</B> and the host sets it with the <B>clCreateBuffer()</B> and <B>clEnqueueWriteBuffer()</B>functions.
</P>
<P ALIGN="justify">
Half float literals need a constructor in CUDA: <B>__half(1.0)</B> but can use a suffix in OpenCL, where <B>1.0h</B> can be used.
</P>
<P ALIGN="justify">
Many operators need a function call in CUDA. The reciprocal in CUDA is <B>hrcp(x)</B> and a simple <= on a half float becomes <B>__hlt(a,b)</B> which makes it less legible.
</P>
<P ALIGN="justify">
A minor diffence is that CUDA's <B>atomicAdd</B> is <B>atomic_add</B> in OpenCL.
</P>
<P ALIGN="justify">
<B>CUDA has asserts</B> but OpenCL does not.
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-34615015229265298422023-04-04T21:39:00.011-07:002023-04-17T12:02:48.449-07:00Minecraft Server<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSFbj1sbhuAOgD5yPe7Byb0mPOhU358A2dqyiRQrqFVgsFpIsnVbF0d9YeWez45ox6RZwbDwu2PkB2mg-Ks_8oVerdjc1qdSAUPbvsG3YkQgm0khUeup7g1DCeaR94xi-tb8arGsTo3XKFnOG5oEvPpNZzR_lUbxMhPHVLicNxqEgbySfbauI7XXpUw/s3840/2023-04-04_21.34.45.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="672" data-original-height="2160" data-original-width="3840" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSFbj1sbhuAOgD5yPe7Byb0mPOhU358A2dqyiRQrqFVgsFpIsnVbF0d9YeWez45ox6RZwbDwu2PkB2mg-Ks_8oVerdjc1qdSAUPbvsG3YkQgm0khUeup7g1DCeaR94xi-tb8arGsTo3XKFnOG5oEvPpNZzR_lUbxMhPHVLicNxqEgbySfbauI7XXpUw/s400/2023-04-04_21.34.45.png"/></a></div>
<P ALIGN="justify">
When it comes to video games, I don't think Minecraft has been surpassed.
Like all the best games, it has a simple premise:
mine blocks in an infinite world, and use them to craft other blocks.
But from this simple fundement, a master piece arose.
</P>
<P ALIGN="justify">
Even after <A HREF="https://twitter.com/notch/status/478766808841732096?s=20">the purchase</A> by Microsoft, the game is still available for Linux, as Mojang maintains a Java version of their game.
Lately, I have been looking into running a server, and intend to write custom code, server-side, to see what can be done with that.
Minecraft lets you modify the client code.
But this post investigates the modification of the Minecraft server.
</P>
<P ALIGN="justify">
Minecraft modding has a long history.
But it appears that my best entry point would be <A HREF="https://www.spigotmc.org/">SpigotMC</A>.
</P>
<P ALIGN="justify">
After executing BuildTools.jar, I ended up with a file called spigot-1.19.3.jar which I copied to my minecraft server root directory. Instead of running minecraft_server.1.19.3.jar I now run the spigot jar file instead.
</P>
<P ALIGN="justify">
To make sure newer minecraft clients can connect, you can put ViaVersion.jar in the plugins directory.
</P>
<P ALIGN="justify">
Next up, is finding out how to write custom server code. So far I have found <A HREF="https://www.youtube.com/playlist?list=PLfu_Bpi_zcDNEKmR82hnbv9UxQ16nUBF7">Kody Simpson's Youtube series</A> an excellent resource.
</P>
<P ALIGN="justify">
Bukkit is a Java Interface, and it is implemented by CraftBukkit.
</P>
<P ALIGN="justify">
CraftBukkit is implemented using net.minecraft.server code.
</P>
<P ALIGN="justify">
This means that the same object can be referenced and used at three different levels.
For instance, the player exists as Bukkit's <B>Player</B>, as CraftBukkit's <B>CraftPlayer</B> and as Mojang's <B>EntityPlayer</B>.
</P>
<P ALIGN="justify">
Only the Bukkit interface remains stable between releases, and can be used on different minecraft server versions.
Also, the NMS (net.minecraft.server from Mojang) code is decompiled, and obfuscated.
</P>
<P ALIGN="justify">
Does coding an NPC require NMS? Or can it be done in SpigotMC? If not, what about PaperMC?
</P>
<P ALIGN="justify">
To deal with the obfuscation of n.m.s. there are the so called <A HREF="https://blog.jeff-media.com/nms-use-mojang-mappings-for-your-spigot-plugins/">Mojang mappings.</A>
Initially I was <A HREF="https://www.spigotmc.org/threads/noclassdeffounderror-net-minecraft-world-entity-npc-villager.600300/#post-4573612">unable to use those with Java 19.</A> But using a development version of <A HREF="https://github.com/md-5/SpecialSource">SpecialSource</A> I was able to use n.m.s. with Java 19.
</P>
<P ALIGN="justify">
When getting confused in API terminology, <A HREF="https://blog.jeff-media.com/bukkit-vs-spigot-api-vs-craftbukkit-vs-spigot/">this is a good reminder</A>.
</P>
<P ALIGN="justify">
I noticed that using the remapped API, really slowed down my iteration speed.
Building my plugin went from a few seconds, to 1 minute, because the remapper is slow.
</P>
<P ALIGN="justify">
The first restults from my experiments: The Little Vex That Could.
A construction-buddy that builds castles from IKEA flat-packs.
</P>
<iframe class="BLOG_video_class" allowfullscreen="" youtube-src-id="yINKO2-qjrI" width="672" height="420" src="https://www.youtube.com/embed/yINKO2-qjrI"></iframe>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-84735719690605414332023-03-27T12:44:00.003-07:002023-03-27T13:04:31.875-07:00Espressif IoT Development Framework<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB6OMQaNUTlFXK7cZfLp0cAVhTgxi63osgzKkRLT0D2dN2jR6fCkw3ln9mbcU0Bo9jebwE967M50Kue3iF-LWOCWxcH1a1s2b4lJZ2DzQmNP9haXC9KIn855chasBkl4_7Ug4Q5D7GM5XBn2ww3rDzbN0ga63BR10L1fZiynghl3EPyoKLeayILL-EEw/s2645/IMG-0410.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="672" data-original-height="2645" data-original-width="2645" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB6OMQaNUTlFXK7cZfLp0cAVhTgxi63osgzKkRLT0D2dN2jR6fCkw3ln9mbcU0Bo9jebwE967M50Kue3iF-LWOCWxcH1a1s2b4lJZ2DzQmNP9haXC9KIn855chasBkl4_7Ug4Q5D7GM5XBn2ww3rDzbN0ga63BR10L1fZiynghl3EPyoKLeayILL-EEw/s600/IMG-0410.jpg"/></a></div>
<P ALIGN="justify">
So far, I have been programming my µcontrollers using the <A HREF="https://www.arduino.cc/en/software">Arduino IDE</A>.
As I progressed with my <A HREF="https://turboledz.com">TurboLEDz</A> experiments, I came across different µcontrollers, including the ESP32 series from Espressif.
</P>
<P ALIGN="justify">
Espressif actually has their own SDK, which targets the command line.
As I feel quite at home on the command-line, I decided to switch over to the Espressif SDK, which is called <A HREF="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html">ESP IDF</A>, or ESP IoT Development Framework.
</P>
<P ALIGN="justify">
This environment is based on cmake and python tools that wrap it.
Nowadays, it recommends to use it with vscode IDE, but frankly, I found it to work better without.
</P>
<P ALIGN="justify">
You mainly interface with the build environment using the <tt>idf.py</tt> tool. The typical sequence would be:
<pre>
$ idf.py set-target esp32s2
$ idf.py build
$ idf.py flash
$ idf.py monitor
</pre>
</P>
<P ALIGN="justify">
And what I really appreciate from ESP IDF is that you can code in pure C, without any C++ stuff involved. No need for <tt>.ino</tt> files, either.
Plain, simple C. I love it.
</P>
<P ALIGN="justify">
Speaking of <A HREF="https://en.wikipedia.org/wiki/Internet_of_things">Internet of Things</A>... I've always found it to be a nebulous term.
But I guess it pertains to devices that don't have a screen, keyboard, mouse, but do have Ethernet/WiFi?
And thanks to the march of progress, those tiny little devices are typically as capable as desktop computers were two decades ago?
</P>
<P ALIGN="justify">
My favourite µcontrollers are RISCV based. And some devices really blur the line between µcontroller and single-board-computer.
Like the Pine64's <A HREF="http://thelittleengineerthatcould.blogspot.com/2022/12/the-8-linux-computer.html">Ox64</A> which is powerful enough to run Linux (but witout the protected memory, I think.)
</P>
<P ALIGN="justify">
I also like the ESP32 with two cores, a lot.
It enabled me to create <A HREF="https://www.tindie.com/products/stolk/voice-changer/">this voice-changer</A> where the two cores can tag-team: one core is computing the Fourier Transformations while the other is doing I2S, and then they switch.
So one core does everything for the odd-numbered batches with samples, and one core does everything for the even-numbered batches.
Nice low-latency concurrency. Yay!
But that project was all in Arduino IDE.
</P>
<P ALIGN="justify">
For my fist IDF project, I wrote a single-header-file piece of code for use with Adafruit's <A HREF="https://learn.adafruit.com/adafruit-led-backpack">LED backpack</A>.
See my <A HREF="https://gist.github.com/stolk/e43647255651c62e962b431bab4fd80d">ledbp.h</A> gist.
It sits on top of Espressif's <A HREF="https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/peripherals/i2c.html">driver/i2c.h</A> code.
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-615607578041951202022-12-16T17:31:00.006-08:002022-12-18T13:32:00.430-08:00The $8 Linux computer (part 2.)
<P ALIGN="justify">
<B>Caveat Emptor!</B> At the time of writing, ethernet, wifi and SD-Card are not working. It's good to realize this before jumping into this.
</P>
<P ALIGN="justify">
Things have improved a little, since writing <A HREF="http://thelittleengineerthatcould.blogspot.com/2022/12/the-8-linux-computer.html">PART 1</A> of my experience.
Instead of a patched bflb-mcu-tool to flash, it is now possible to use a <a href="https://github.com/raspberrypi/picoprobe/compare/master...sanjay900:picoprobe:master">modified picoprobe</a>
[<A HREF="https://github.com/sanjay900/picoprobe/releases">DOWNLOAD HERE</A>]
with the <A HREF="https://dev.bouffalolab.com/download">Dev Cube</A> flashing tool.
</P>
<P ALIGN="justify">
Also, there is <a href="https://github.com/bouffalolab/bl808_linux/blob/main/patch/m1sdock/m1sdock_uart_pin_def.patch">a patch for the PIN definitions</a> so that we can capture the UART of the D1 core (which is a T-HEAD C906) on pins GPIO17/GPIO16.
</P>
<P ALIGN="justify">
With the fixed pin definitions we can hook up a USB to UART dongle, like the CH340G, to the second UART as shown below.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWFoF6xAhuPV0SzG_ABJC1BkY8xWn3a9Kus7A0AhW_cImEGwmEpHCnIiAGNAk1uSkygAXZMChnkOlG4I-bhQc14jJu_bTE_8fsY0g7LgVJS4-Mk5LZNSy48sAq0WkJaZSx1S6TUkL5E7uuyiKa9gpwgJvv0tnbYqrkdh07PZIyAgYe7ua7r1DjqoOk3g/s1463/wiring-kb2040-ox64-ch340.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="672" data-original-height="934" data-original-width="1463" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWFoF6xAhuPV0SzG_ABJC1BkY8xWn3a9Kus7A0AhW_cImEGwmEpHCnIiAGNAk1uSkygAXZMChnkOlG4I-bhQc14jJu_bTE_8fsY0g7LgVJS4-Mk5LZNSy48sAq0WkJaZSx1S6TUkL5E7uuyiKa9gpwgJvv0tnbYqrkdh07PZIyAgYe7ua7r1DjqoOk3g/s600/wiring-kb2040-ox64-ch340.png"/></a></div>
<P ALIGN="justify">
In this picture, the red dongle is to capture the output from the linux console running on the T-HEAD C906 core.
The pink dongle is to program the Ox64.
Both of these need to be connected to your PC.
The Ox64 itself needs no connection to the PC, other than a power feed into the Micro-USB.
</P>
<P ALIGN="justify">
So, once we wired this all up, flashed to binaries, what do we get?
</P>
<P ALIGN="justify">
<B>We get root!</B>
</P>
<P ALIGN="justify">
And that's after booting in a blistering 0.22 seconds!
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5YCm3rAlx06nIdxQuRjpsz7kRGcya5HRLJ_dhPLqSWtWRHTwfGUHyPc7SfFCgCkMYkWTuHp1flzdk3YL0GTiggMSlKljemOa7NqYj6dd-ILDEQcWOMN6Oyz--wQH_S9EbYVMGypTRnt65K1WD2M8GQELVSX25OsT8KF7n4NIkty5xAHfDqjb2juxz3A/s1600/term-riscv.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="689" data-original-width="1122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5YCm3rAlx06nIdxQuRjpsz7kRGcya5HRLJ_dhPLqSWtWRHTwfGUHyPc7SfFCgCkMYkWTuHp1flzdk3YL0GTiggMSlKljemOa7NqYj6dd-ILDEQcWOMN6Oyz--wQH_S9EbYVMGypTRnt65K1WD2M8GQELVSX25OsT8KF7n4NIkty5xAHfDqjb2juxz3A/s1600/term-riscv.png"/></a></div>
<P ALIGN="justify">
<A HREF="https://gist.github.com/stolk/c17781c295171b1b40e3aebee0220735">Full boot log.</A>
</P>
<P ALIGN="justify">
I love Linux on a diet. So mean and lean.
</P>
<P ALIGN="justify">
Next up: Can we get networking?
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com3tag:blogger.com,1999:blog-7776021459998532494.post-54650689835263376162022-12-15T17:49:00.005-08:002022-12-18T13:47:31.938-08:00The $8 linux computer (part 1.)<P ALIGN="justify">
Yes, you read that right... for <A HREF="https://pine64.com/product/128mb-ox64-sbc-available-on-december-2-2022/
">$8</A> you can run linux on a RISC-V computer.
And not just a stripped down kernel without an MMU.
No, the Ox64 comes with capable RISC-V cores.
Heck, and not just one core, but three cores (all different.)
Exciting times!
</P>
<P ALIGN="justify">
<B>Caveat Emptor!</B> At the time of writing, ethernet, wifi and SD-Card are not working. It's good to realize this before jumping into this.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMR6WHmKku5veDN9XI3ZTSOw9dSsNTbCsuJ6LSSxejLaYPTO-V71zPoc_-fpF0QYx260DGx5RSEsx58z-xxsujTZLugdjAs_7uaG6YZMdHBxrGaxlx9Q-H-NYszKY7-pvv1bfxEtmH1C3HZSoVBlkm5kdangQQyXUyRGFX8ja04tWg6ZzwsNs_9DuJJA/s3114/ox64.jpeg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="672" data-original-height="2084" data-original-width="3114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMR6WHmKku5veDN9XI3ZTSOw9dSsNTbCsuJ6LSSxejLaYPTO-V71zPoc_-fpF0QYx260DGx5RSEsx58z-xxsujTZLugdjAs_7uaG6YZMdHBxrGaxlx9Q-H-NYszKY7-pvv1bfxEtmH1C3HZSoVBlkm5kdangQQyXUyRGFX8ja04tWg6ZzwsNs_9DuJJA/s600/ox64.jpeg"/></a></div>
<P ALIGN="justify">
It looks like a microcontroller, but behaves like a UNIX machine. Sweet, or what?
Getting it up and running, though, is far from trivial.
There are so many hurdles to take!
</P>
<P ALIGN="justify">
<b>Hurdle 1</b>: You cannot program it using USB, like you would an Arduino, ESP32, Stamp-C3 or rPi Pico.
Nope... this needs to be programmed via the UART TX/RX pins.
In the picture above, you can see them hooked up to GPIO14 / GPIO15 and GND.
</P>
<P ALIGN="justify">
<b>Hudle 2</b>: The flashing tool Dev Cube will crash on launch when using Ubuntu on Wayland: you have to switch to Xorg instead.
</P>
<FONT SIZE=2>
<PRE>
$ ./BLDevCube-ubuntu
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
/usr/lib/x86_64-linux-gnu/gio/modules/libdconfsettings.so: undefined symbol: g_log_structured_standard
Failed to load module: /usr/lib/x86_64-linux-gnu/gio/modules/libdconfsettings.so
GLib-GIO-Message: Using the 'memory' GSettings backend. Your settings will not be saved or shared with other applications.
(BLDevCube-ubuntu:54646): GLib-GIO-ERROR **: Settings schema 'org.gnome.settings-daemon.plugins.xsettings' does not contain a key named 'antialiasing'
Trace/breakpoint trap (core dumped)
</PRE>
</FONT>
<P ALIGN="justify">
So, UART programming then... fine, we'll just use one of those little CH340G dongles.
I got <A HREF="https://www.amazon.ca/gp/product/B07V556Q82">one</A> off Amazon, but it would not work... every time the handshake would fail in Dev Cube (<b>hurdle 3</b>).
</P>
<P ALIGN="justify">
Luckily, <a href="https://discord.com/channels/463237927984693259/771032441971802142">some people</a> found out that you can program it with an RP2040 device, like the rPi Pico.
I had a <a href="https://learn.adafruit.com/adafruit-kb2040">KB2040</a> from Adafruit lying around, so used that.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhouPPAyy5QKp275xjz4VaBCd191CAfVXivIQuqxSTve9OUbJwR7grqbrIPH1_GwGg6hCsev-2UL4hHoH3kECmDA-k4my1h4_Tbq_qc0I-h8xDG1U6HPCoyXmhfM0Kutb-rT3xyBM5-MwIvEEpIxzTjHyJd54uagXfUMMCpiRZLPRU-aHsJOCggKwi1Pg/s1618/kb2040.jpeg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="672" data-original-height="1178" data-original-width="1618" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhouPPAyy5QKp275xjz4VaBCd191CAfVXivIQuqxSTve9OUbJwR7grqbrIPH1_GwGg6hCsev-2UL4hHoH3kECmDA-k4my1h4_Tbq_qc0I-h8xDG1U6HPCoyXmhfM0Kutb-rT3xyBM5-MwIvEEpIxzTjHyJd54uagXfUMMCpiRZLPRU-aHsJOCggKwi1Pg/s600/kb2040.jpeg"/></a></div>
<P ALIGN="justify">
Which puts us at <b>hurdle 4</b>: How to turn a KB2040 into a serial bridge between PC and Ox64?
Hook up GPIO-4 of the RP2040 to GPIO-15 of the Ox64. Hook up GPIO-5 of the RP2040 to GPIO-14 of the Ox64.
Also, connect the grounds, of course.
See below how to hook up for flashing the M0.\
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM9Xafi7eeiz0tNQWMUX4pULaTq4VGeupNLwmk-ox-bT6ESlBtjhC3ZxsI72G3c74a85T5lHmr96pv_wlREMl1u7Lqz2mlReGCn5AZ4Y7VXfv6UfdvutWR0wTUPW_6WRktiA_kXWlSAQ-zRkcV9620lXUIZmMTihFAKWqOllqFfIbvdVvKN_-7Uh0s7Q/s1463/wiring-kb2040-ox64.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="672" data-original-height="934" data-original-width="1463" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM9Xafi7eeiz0tNQWMUX4pULaTq4VGeupNLwmk-ox-bT6ESlBtjhC3ZxsI72G3c74a85T5lHmr96pv_wlREMl1u7Lqz2mlReGCn5AZ4Y7VXfv6UfdvutWR0wTUPW_6WRktiA_kXWlSAQ-zRkcV9620lXUIZmMTihFAKWqOllqFfIbvdVvKN_-7Uh0s7Q/s600/wiring-kb2040-ox64.png"/></a></div>
<P ALIGN="justify">
Then we need to load our RP2040 with <A HREF="https://github.com/raspberrypi/picoprobe">picoprobe</A> which we can do by holding BOOT while powering up, and feeding it the uf2 file with picoprobe.
</P>
<P ALIGN="justify">
Ok, so now we can flash it then? Unfortunately, no, <b>hurdle 5</b>: DevCube is still not able to flash the Ox64, but we can use <a href="https://pypi.org/project/bflb-mcu-tool/">bflb-mcu-tool</a> instead.
</P>
<P ALIGN="justify">
Ok, but with bflb-mcu-tool, we are all set! Are we?
Introducing <b>hurdle 6</b>: we need to modify the tool before it will work for us.
This means stripping DTR and RTS stuff from the tool by editing the
~/.local/lib/python3.10/site-packages/bflb_mcu_tool/libs/bflb_interface_uart.py file.
Here is <A HREF="https://gist.github.com/stolk/46228d2b7ab0ca5b0ff98a4ce3b2c6fe">my copy</A>.
</P>
<P ALIGN="justify">
So with the Ox64 powered via MicroUSB, and the RP2040 connected to my PC using USB-C, I can finally flash something.
For that, I took the low_load_bl808_m0.bin from the <a href="https://github.com/bouffalolab/bl808_linux">bl808 linux guide</a> and flashed it with:
<FONT SIZE=2>
<PRE>
$ bflb-mcu-tool --chipname=bl808 --port=/dev/ttyACM2 --baudrate=2000000 --firmware=out/low_load_bl808_m0.bin
</PRE>
</FONT>
</P>
<P ALIGN="justify">
After which I now get output from my Ox64, via my KB2040 to my PC:
<FONT SIZE=2>
<PRE>
dynamic memory init success,heap size = 156 Kbyte
E907 start...
mtimer clk:1000000
psram clk init ok!
</PRE>
</FONT>
</P>
<P ALIGN="justify">
Ok, a modest start, but the Ox64 is talking to my PC now! Yay!
Come back to my blog at a later time to see if I will manage to run Linux on the Ox64!
Because as I understand it, I also need to flash something to the D0 and then flash the actual OS as well.
</P>
<P ALIGN="justify">
<B>UPDATE:</B> Here is <A HREF="https://thelittleengineerthatcould.blogspot.com/2022/12/the-8-linux-computer-part-2.html">PART 2</A>.
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com3tag:blogger.com,1999:blog-7776021459998532494.post-19035838267651681112022-04-30T11:13:00.001-07:002022-04-30T11:13:26.095-07:00TurboLEDz Voice Changer.<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLPH4CeG8_ASEya56XXqWLnrGNyxekxWIWjdyhxHbAE26a3ri98BMrNHaL_MazVA-h3D1irjo8g3zcdQWFpioyWZb3XQ5wfXocjDZ5YFGXRDVkBEQ0jhldxLTtNHLd0ZmahnMZUtr4ib2JmDvpCNgkttsUoMyn9s8YoEHjHAk3tzgEOs2J-KDsnn50OQ/s1247/voice_board.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="913" data-original-width="1247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLPH4CeG8_ASEya56XXqWLnrGNyxekxWIWjdyhxHbAE26a3ri98BMrNHaL_MazVA-h3D1irjo8g3zcdQWFpioyWZb3XQ5wfXocjDZ5YFGXRDVkBEQ0jhldxLTtNHLd0ZmahnMZUtr4ib2JmDvpCNgkttsUoMyn9s8YoEHjHAk3tzgEOs2J-KDsnn50OQ/s600/voice_board.png"/></a></div>
<P ALIGN="jutify">
I've released the 6th product under the <a href="https://turboledz.com/">TurboLEDz</a> name.
This time it is a <a href="https://www.tindie.com/products/stolk/voice-changer/">voice changer</a>.
It makes you sound like a bad asss, by doing real time FFT, frequency manupulation and iFFT to go back to the time domain.
It's built with an I2S mic and I2S DAC/Amplifier.
To make the μcontroller capable of keeping up with the samples, I've programmed it as multi-threaded, dual core.
So if one core is busy doing math, the other is still available to do IO.
And the cores will tag-team. One core for the even numbered chunks, the other core for the odd numbered chunks.
It works really well, as you can see in the video.
</P>
<iframe width="656" height="400" src="https://www.youtube.com/embed/xKQY6byU_EQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-11159380822918408772022-04-24T19:54:00.003-07:002022-04-29T17:28:21.781-07:00Super Capacitors<P ALIGN="justify">
I bought three super capacitors from Adafruit, model <a href="https://cdn-shop.adafruit.com/datasheets/dl-dle-e-140101.pdf">DDLE2R5LGN701KAA5S</a>.
They are rated at 700 Farad at 2.5V. (They have very little stock left, at time of writing, so if you want them too, act quickly!)
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3-25ePiy77X6x28zbmoJp14fwlgKbTSXRhjGmJSp4dHwzyfZQcAoPk9iUGkVdAuJNB7ZQqU2YnUk2BapMn2nOcaiKQaA3voF7bNKU0fkjc5CE0Zpz3sIx_UKq4OfQ6sPFe7K_MOHNe1kBj-90OAh9ziNCXmtDQB7T1L5EshK_RjiuRufRjaIma6mokw/s970/1885-05.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="728" data-original-width="970" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3-25ePiy77X6x28zbmoJp14fwlgKbTSXRhjGmJSp4dHwzyfZQcAoPk9iUGkVdAuJNB7ZQqU2YnUk2BapMn2nOcaiKQaA3voF7bNKU0fkjc5CE0Zpz3sIx_UKq4OfQ6sPFe7K_MOHNe1kBj-90OAh9ziNCXmtDQB7T1L5EshK_RjiuRufRjaIma6mokw/s600/1885-05.jpg"/></a></div>
<P ALIGN="justify">
If I place them in series, I will end up with 233 Farad at the very maximum of 7.5V.
However, charging to the max 7.5V is dangerous: one of the capacitors can easily overcharge and explode, that way.
Unless you balance the capacitors.
</P>
<P ALIGN="justify">
Balancing a capacitor bank is not trivial.
But there seems to be <a href="https://www.instructables.com/Lets-learn-about-Super-Capacitors-A-Practical-G/">an alternative</a>, as offered by Patrick of EngineeringShock.
</P>
<P ALIGN="justify">
Patrick's advice is to charge the capacitors to 80% of their nominal Voltage, so that even if there is a mismatch in internal resistance between the capacitors in series, none of them will overcharge.
I like this approach, as it is simpler, does not require extra circuitry, at the cost of lost capacitance.
</P>
<P ALIGN="justify">
So if we charge a 7.5V bank to 80%, we get a charging voltage of 6 Volts. Let's make that our target. When we have have our bank charged to 6V, we can feed that into a voltage regulator, and as the bank drains to 3.3V, we should be able to ride from 6V to 3.3V and run a μcontroller off that, or some other low-power electronics.
</P>
<P ALIGN="justify">
And this leads me to my next objective: how to generate a steady 6V charging voltage? I would like to use solar panels for this.
So let's dive into photovoltaics.
</P>
<P ALIGN="justify">
Reading the specification of a PV panel, there is the nominal voltage, which we can't really rely on.
Then there is the Voc (<a href="https://www.pveducation.org/pvcdrom/solar-cell-operation/open-circuit-voltage">Open Circuit Voltage</a>) which we will measure if there is no current flowing.
And also the Max Power Voltage, which is lower.
</P>
<P ALIGN="justify">
I need to read up on how to make sure that a photovoltaic panel output a steady 6V, and never any higher, at a tight tolerance.
PV panels typically use charge controllers for that, but I want something simple.
Maybe an opamp?
</P>
<H2>UPDATE</H2>
<P ALIGN="justify">
I am taking a different approach. I've decided to charge the capacitors in parallel, not in series, at a steady 2.5V.
</P>
<P ALIGN="justify">
To achieve this, I take input from a solar panel (with wildly varying voltage, and current) and convert that with a buck-converter to 2.5V that can be used to charge the capacitors.
</P>
<P ALIGN="justify">
I then use the capacitors as input for a boost-converter that brings a varying low voltage (It is only 2.5V when fully charged, and they discharge linearly) to a steady 3.3V.
This I can then use in a client circuit, typically a μcontroller with some peripherals attached.
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-24971606150321207842022-04-13T11:28:00.013-07:002022-05-24T17:12:15.705-07:00Lychee RV 86<P ALIGN="justify">
Just for the heck of it, I am test-driving a RISCV Linux SBC called the <A HREF="https://linux-sunxi.org/Sipeed_Lichee_RV">Sipeed Lychee</A> RV 86.
</P>
<P ALIGN="justify">
When I plugged it in, nothing happened. No console ouput on the USB tty, nothing on the screen.
It turns out there is no software loaded on it: the flash memory slot is empty. So you need to provide your own storage, and own OS.
</P>
<P ALIGN="justify">
First attempt is with a "debian-minimal" install.
</P>
<FONT SIZE=2><PRE>
# dd if=debian-minimal-licheerv.img of=/dev/sdb bs=32K
134272+0 records in
134272+0 records out
4399824896 bytes (4.4 GB, 4.1 GiB) copied, 248.155 s, 17.7 MB/s
</PRE></FONT>
<P ALIGN="justify">
Those were the write speeds to my "Sandisk Extreme PLUS." Hmm... that does not seem to be an extreme speed, to me. It has a U3 designation. Oh well.
UPDATE: Lexar x1000 was even worse: 15.7 MB/s and the write speed slows down, as you write more. Remind me never to buy Lexar SD cards again.
</P>
<P ALIGN="justify">
And it works!
With the card inserted, I now get a login prompt on ttyUSB0 in 32 seconds. Not bad at all.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2cQbmv7W_qXbwdacFEqHc-18cQEy1DeHoycVjc_QptLfk3FlMO0Y2bsXgQiV2VJfwdoCFWAyBsddv4_zyrkalYGUjoQ4aYHmxUmXUa11sHj4QAnulEsYC2Rdyq9NRvpasRJbHtyyJBt-ER-FDWrwex6HjwCOnBev9ypp0QiJfKCfLIzaI9CenxtSRug/s1600/loginscreen.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="587" data-original-width="822" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2cQbmv7W_qXbwdacFEqHc-18cQEy1DeHoycVjc_QptLfk3FlMO0Y2bsXgQiV2VJfwdoCFWAyBsddv4_zyrkalYGUjoQ4aYHmxUmXUa11sHj4QAnulEsYC2Rdyq9NRvpasRJbHtyyJBt-ER-FDWrwex6HjwCOnBev9ypp0QiJfKCfLIzaI9CenxtSRug/s1600/loginscreen.png"/></a></div>
<P ALIGN="justify">
Somehow, it takes a long time for the Ethernet device to show up with ifconfig command?
When it does, <b>ifup usb0</b> is not working: <i>ifup: unknown interface usb0</i>
</P>
<P ALIGN="justify">
When I make usb0 interface known, the dhcp client will receive no offers, unfortunately. Despite the Ethernet light blinking, so there is network activity.
</P>
<H2>UPDATE</H2>
<P ALIGN="justify">
I have been able to work around the need for a proprietary MSWindows tool to use the Lichee RV disk images.
With the <A HREF="https://github.com/YuzukiTsuru/OpenixCard">OpenixCard</A> tool, you can extract a normal image, that you can write with dd to an SDCARD.
</P>
<FONT SIZE=2>
<PRE>
$ file ~/Downloads/LicheeRV_Debian_86_480p.img
/home/bram/Downloads/LicheeRV_Debian_86_480p.img: data
./OpenixCard -i ~/Downloads/LicheeRV_Debian_86_480p.img -d
...
$ file /home/bram/Downloads/LicheeRV_Debian_86_480p.img.dump.out/LicheeRV_Debian_86_480p.img
/home/bram/Downloads/LicheeRV_Debian_86_480p.img.dump.out/LicheeRV_Debian_86_480p.img: DOS/MBR boot sector; partition 1 : ID=0xc, start-CHS (0x2,35,2), end-CHS (0x2,163,1), startsector 34336, 8064 sectors; partition 2 : ID=0xee, start-CHS (0x0,0,2), end-CHS (0x0,33,1), startsector 1, 2079 sectors
$ sudo dd if=/home/bram/Downloads/LicheeRV_Debian_86_480p.img.dump.out/LicheeRV_Debian_86_480p.img of=/dev/sdb bs=1M
8237+1 records in
8237+1 records out
8637726720 bytes (8.6 GB, 8.0 GiB) copied, 435.776 s, 19.8 MB/s
</PRE>
</FONT>
<H2>UPDATE</H2>
<P ALIGN="justify">
The Debian image works great. I removed all X11 stuff, and will just use fb0.
</P>
<P ALIGN="justify">
I noticed that eth0 mac address is randomized at each boot, so I had to create an entry in /etc/network/if-pre-up file:
</P>
<FONT SIZE=2>
<PRE>
#!/bin/sh
IFCONFIG=/sbin/ifconfig
if [ ! -x $IFCONFIG ]; then
exit 0
fi
if [ "$IFACE" = eth0 ]; then
$IFCONFIG $IFACE hw ether XX:XX:XX:XX:XX:XX
fi
</PRE>
</FONT>
<H2>UPDATE</H2>
<P ALIGN="justify">
To set the timezone: $ timedatectl set-timezone America/Vancouver
</P>
<P ALIGN="justify">
If not using wifi, it is probably a good idea to remove xr829 from /etc/modules file.
</P>
<P ALIGN="justify">
I have been removing a lot of packages, trying to get a minimal install.
To aide this effort, I decided to graph the dependencies, to see which cuts I can make in the dependency chains.
</P>
<IMG WIDTH=1024 SRC="https://stolk.org/tmp/dependencies.dot.svg">
<H2>UPDATE</H2>
<P ALIGN="justify">
The <A HREF="https://linux-sunxi.org/D1"> D1 CPU</A> is RV64IMAFDCVU which means it does: INTEGER MUL/DIV, Atomic, SP FP, DP FP, Compressed Instructions, Vector Operations, User.
</P>
<P ALIGN="justify">
Sadly, it has <A HREF="https://stackoverflow.com/questions/72340698/riscv-branchless-coding">no conditional move operations</A>.
</P>
<H2>UPDATE</H2>
<P ALIGN="justify">
Tyring to build a new kernel for this, using <A HREF="https://linux-sunxi.org/Allwinner_Nezha#Mainline_U-Boot">these instructions</A>.
Oof! getting the linux kernel source with git history... 5.2GByte.
These sizes of these things are getting out of hand.
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-9940813720832706782022-04-13T10:19:00.001-07:002022-04-13T10:19:38.636-07:00Desk-side Stock Ticker by TurboLEDz.<P ALIGN="justify">
TurboLEDz has released another product: the <a href="https://www.tindie.com/products/stolk/deskside-stock-ticker/">Desk-side Stock Ticker</a>.
It connects to WiFi with WPS, and automatically retrieves stock quotes from the Internet.
</P>
<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/vTcj5v6aNJ">pic.twitter.com/vTcj5v6aNJ</a></p>— TurboLEDz (@TurboLEDz) <a href="https://twitter.com/TurboLEDz/status/1513947671773401092?ref_src=twsrc%5Etfw">April 12, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-89871024754763747312022-03-19T11:36:00.003-07:002022-03-19T11:37:16.837-07:00Newest member of the TurboLEDz family: the CPU Odometer!<P ALIGN="justify">
A CPU does not wear down with use like a car engine does.
Hence, a car has an Odometer, and a CPU does not.
I does not need one.
</P>
<P ALIGN="justify">
But, just because it doesn't need one, does not mean it cannot have one!
I decided to make one.
World.... please meet the <A HREF="https://www.tindie.com/products/stolk/cpu-odometer/">TurboLEDz CPU Odometer</A>.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjh3MIuPeAQVxSf5bM9JiYsgE50SVekgjqs0GA57z2Q7AOwZKnE0qMVV0Uw75Dc4AEgoiBLc5G5SVDK7wvDneWkWC9xatlnYyFT8kIEOwuR6RpO6IrGbIOuXSymY3fAYkgQSsAhT53DiStLegRkZnPZ0FjWdnI3rZYskIbGxOfT5gvJEbJJwjXo0GMegQ=s1200" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="800" data-original-width="1200" src="https://blogger.googleusercontent.com/img/a/AVvXsEjh3MIuPeAQVxSf5bM9JiYsgE50SVekgjqs0GA57z2Q7AOwZKnE0qMVV0Uw75Dc4AEgoiBLc5G5SVDK7wvDneWkWC9xatlnYyFT8kIEOwuR6RpO6IrGbIOuXSymY3fAYkgQSsAhT53DiStLegRkZnPZ0FjWdnI3rZYskIbGxOfT5gvJEbJJwjXo0GMegQ=s600"/></a></div>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg8F6Brx5c3AaRH4cz4JSSsKXpUmIXaQhJa2AScCxWHOG7hYltwd7S5JmleG6gLqvfOdOIex0tH6q7X6m2aQXTGkH2kg5_imypqqXE04Iw_Xn0b4aHYD36J58Me1tBd5d3qiuBBsc48qHf3uizHeJAfhXBLk3FFNQW4XzcXrUNCU1s-O6ZpxWAWvaZFuw=s1200" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="800" data-original-width="1200" src="https://blogger.googleusercontent.com/img/a/AVvXsEg8F6Brx5c3AaRH4cz4JSSsKXpUmIXaQhJa2AScCxWHOG7hYltwd7S5JmleG6gLqvfOdOIex0tH6q7X6m2aQXTGkH2kg5_imypqqXE04Iw_Xn0b4aHYD36J58Me1tBd5d3qiuBBsc48qHf3uizHeJAfhXBLk3FFNQW4XzcXrUNCU1s-O6ZpxWAWvaZFuw=s600"/></a></div>
<P ALIGN="justify">
It uses the <A HREF="https://github.com/stolk/turboledz">turboledz daemon</A> for Linux to keep track of the jiffies (centiseconds) that were spent computing, aggregated over all cores.
If your computer is idling, it ticks very slowly.
If your computer is pinning all cores at 100% it ticks up very fast.
The odometer value is stored in between reboots on your system.
</P>
<P ALIGN="justify">
I am selling it on <A HREF="https://www.tindie.com/stores/stolk/">my tindie store</A>.
</P>
<center>
<iframe width="608" height="360" src="https://www.youtube.com/embed/fVoNG-5Kgvo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</center>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-7238549548430079042022-01-30T18:20:00.001-08:002022-02-02T16:42:24.305-08:00BSD<P ALIGN="justify">
I'm doing my first exploration of BSD.
After some struggles with the OpenBSD installer, I installed FreeBSD instead.
Here as some findings.
</P>
<P ALIGN="justify">
You can install software from source in /usr/ports and to do that, you need the portsnap command to fetch the tree.
</P>
<P ALIGN="justify">
My 1280x768 monitor is used as a 640x480 console.
I tried the following in /boot/loader.conf which did not work:
</P>
<PRE>
kern.vt.fb.default_mode="1280x768"
efi_max_resolution="1280x768"
</PRE>
<P ALIGN="justify">
I tried to use hidraw using this in loader.conf which also did not work for me:
</P>
<PRE>
hidraw_load="YES"
hw.hid.hidraw.debug="9"
hw.hid.hidbus.debug="99"
hw.usb.uhid.debug="99"
</PRE>
<P ALIGN="justify">
My 12th gen Intel machine cannot boot version 13 of BSD.
Instead I need to use 14-CURRENT.
</P>
<P ALIGN="justify">
I could only get the installer for 14-CURRENT to run by installing a discrete Radeon GPU, which then let me set the BIOS option CSM enabled.
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-34706423653850000692022-01-14T21:59:00.001-08:002022-01-14T21:59:59.634-08:00TurboLEDz<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhca1D1zbYeEa7QFLTjTB-_3nLb_pCFHHdPCO8iDSiQ-6AQ6prBeUVOzG3jRUinHwiWBjnwPpiomeESman9Tbkx14sI443Vryz8h3ktpFKL9c78Yf9t23__QPF2G35rCvVD6Xeg5ZWhAGjUGLuIFOUoU_R9uKhfuqZqC7KxdJ-eo5T6UugsWNp1QclR3w=s3300" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="2200" data-original-width="3300" src="https://blogger.googleusercontent.com/img/a/AVvXsEhca1D1zbYeEa7QFLTjTB-_3nLb_pCFHHdPCO8iDSiQ-6AQ6prBeUVOzG3jRUinHwiWBjnwPpiomeESman9Tbkx14sI443Vryz8h3ktpFKL9c78Yf9t23__QPF2G35rCvVD6Xeg5ZWhAGjUGLuIFOUoU_R9uKhfuqZqC7KxdJ-eo5T6UugsWNp1QclR3w=s600"/></a></div>
<P ALIGN="justify">
Game Studio Abraham Stolk Incorporated, has done a pivot.
No games, for now, instead: consumer electronics.
</P>
<P ALIGN="justify">
Yep, I have refashioned myself as a electronics designer.
And my new brand is <A HREF="https://turboledz.com">TurboLEDz</A>.
</P>
<P ALIGN="justify">
These devices will plug in your motherboard USB, and are to be mounted in your PC case.
They will then display either the CPU load (Model88s) or the CPU Core Frequencies (Model810c) as a running graph.
</P>
<P ALIGN="justify">
You can buy them on my <A HREF="https://www.tindie.com/stores/stolk/">Tindie Store</A>.
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-45751636688512687882021-11-11T10:07:00.000-08:002021-11-11T10:07:03.972-08:00Bugs in Complex Software<div class="separator" style="clear: both;"><a href="https://upload.wikimedia.org/wikipedia/commons/f/ff/First_Computer_Bug%2C_1945.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="583" data-original-width="740" src="https://upload.wikimedia.org/wikipedia/commons/f/ff/First_Computer_Bug%2C_1945.jpg"/></a></div>
In the picture: history's first bug.
<P ALIGN="justify">
Complex software will be guaranteed to have bugs in it.
And most of the bugs are caused by state changes.
</P>
<P ALIGN="justify">
The human mind has limited capacity of keeping track of state (data, variables.)
Hence, there is a discrepancy between what the state looks like in the programmer's mind, and what it actually looks like.
</P>
<P ALIGN="justify">
<b>How</b> does state change?
</P>
<P ALIGN="justify">
<b>Where in the code</b> does the state change?
</P>
<P ALIGN="justify">
<b>When</b> does the state change?
</P>
<P ALIGN="justify">
<b>In what order</b> does the state change?
</P>
<P ALIGN="justify">
And even... <b>why</b> doest the state change?
</P>
<P ALIGN="justify">
The mental picture of those, formed by the programmer, is very poor.
</P>
<P ALIGN="justify">
So.. bugs!
</P>
<P ALIGN="justify">
There is of course a paradigm where state-change plays a zero roll: functional programming.
But despite decades of trying, we have not been able to practically use that in complex software.
Mainly because the real world deals with state.
Try making a video game that carries no state!
</P>
<P ALIGN="justify">
John Carmack once did an <a href="https://youtu.be/1PhArSujR_A?t=1242">impromptu talk on functional programming</a> and video games, and made in interesting observation that you could write an AI/sim that takes the entire world as function input, and produces the entire world as its output.
</P>
<P ALIGN="justify">
About John's example of a one-person hallway... I think the solution is simple. Input for hall-entering needs more than the current entity. It needs a list of all other entities that want to enter. Then use a heuristic to choose which one can actually enter. Done.
</P>
<P ALIGN="justify">
So yeah... complex state changes.
As long as we have not harnessed the complexity of state, I find it pretty futile to crusade against C's unsafe memory referencing, e.g.
A bug caused by following a dangling pointer is so shallow, compared to a bug caused by asynchronous state changes racing to completion.
Throw in multiple threads, multi-player, and it will be too hard to reason about.
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-36408312443105731452021-11-07T09:02:00.000-08:002021-11-07T09:02:02.701-08:00Switching<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeGnS1hDmwvXzlwQ-yeSCb4syAtv0c1fwOZZWodXapXgubugCI_O-H3xCJcFj6-3GXWVYolKu7_-1GP8-k5NOtfv6KSPaHFa-KkMAkAkga51TtjsN2nzYpheqjO4JEFwWxBF0y7oArs4PE/s1638/IMG-8812.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1638" data-original-width="1638" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeGnS1hDmwvXzlwQ-yeSCb4syAtv0c1fwOZZWodXapXgubugCI_O-H3xCJcFj6-3GXWVYolKu7_-1GP8-k5NOtfv6KSPaHFa-KkMAkAkga51TtjsN2nzYpheqjO4JEFwWxBF0y7oArs4PE/s600/IMG-8812.jpg"/></a></div>
<P ALIGN="justify">
I've been learning a lot about transistors, lately.
This is because I found myself having to switch a load that would be too large for an IO pin.
Here I summerize my newly gathered knowledge on them.
</P>
<P ALIGN="justify">
A BJT transistor is switched ON/OFF using current at the base.
This current is then multiplied at Collector/Emitter.
</P>
<P ALIGN="justify">
To tune the current flowing through the base, we need a bias resistor.
This makes PCB design bulkier, but you can get pre-biased transistors.
I find I need to get them with a low Ohm bias, else my transistor will not switch fully on.
</P>
<P ALIGN="justify">
BJT comes in two variants, NPN and PNP.
The schematic symbol differs in which way the arrow points.
Mnemonic: NPN has the arrow "Not Pointing iN."
</P>
<P ALIGN="justify">
PNP transistors can be used to switch a load at its high-side: You cut the load's connection to V+ ON/OFF.
</P>
<P ALIGN="justify">
NPN transistors can be used to switch a load at its low-side: You cut the load's connection to GND ON/OFF.
</P>
<P ALIGN="justify">
MOSFET transistors are often a better choice, unlike of BJT's current based switching, the switch based on voltage at the gate.
</P>
<P ALIGN="justify">
MOSFET comes in two variants, P-CHANNEL and N-CHANNEL.
</P>
<P ALIGN="justify">
P-CHANNEL transistors can be used to switch a load at its high-side: You cut the load's connection to V+ ON/OFF.
A 0V at the gate will switch on the transistor. Source is connected to V+ and Drain is connected to the load.
</P>
<P ALIGN="justify">
N-CHANNEL transistors can be used to switch a load at its low-side: You cut the load's connection to GND ON/OFF.
A V+ at the gate will switch on the transistor.
Source is connected to GROUND and Drain is connected to the load.
</P>
<P ALIGN="justify">
To simplify a PCB design, you can get two transistors that share its housing in an "Array."
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
<P ALIGN="justify">
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-19373549465862799462021-10-27T16:14:00.002-07:002021-10-27T16:18:21.400-07:00Bi-Colour LED bars.<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='600' height='498' src='https://www.blogger.com/video.g?token=AD6v5dyQfC7KiBngN9RPxaG71co0V-Obg5B9X0YiSwhiLqnDGQ1UJzFQoqetpJQNtFWpKigVIgzRkAqMHhLqSn6_9g' class='b-hbp-video b-uploaded' frameborder='0'></iframe>
<P ALIGN="justify">
I am evaluating bi-colour LEDs that are RED/GRN, and can be mixed to ORANGE/YELLOW.
The two candidates are <A HREF="http://www.sunled.com/attachments/file/psearch/000/00/00/GMDKVGX10D(V5-X).pdf">SunLED GMDKVGX10D</A> and <A HREF="https://www.kingbrightusa.com/images/catalog/SPEC/DC10EGWA.pdf">KingBright DC10EGWA</A>.
</P>
<P ALIGN="justify">
I've found that the SunLED has a bright GREEN with an even brighter RED.
You need to drive the green channel with at least double the current of the red, to match them.
I find that 1kΩ and 2kΩ work for my application.
</P>
<P ALIGN="justify">
The KingBright, on the other hand, doesn't show much difference between the RED and GRN brightness.
But both are far less bright than the SunLED.
Even though the KingBright has the term "High Efficiency" in the data sheet?
When I limit both RED and GRN with 470Ω I find it is still quite a bit dimmer than the SunLED at 1kΩ/2kΩ.
</P>
<P ALIGN="justify">
What both models do the same: they have the GRN/RED LEDs share their cathode, not their anode.
A common-anode design would have been so much more convenient.
You would have been able to drive it with a constant current LED driver that is a current sink.
All constant current LED drivers that I could find are current sinks, so none of them can be used with these LEDs.
So not Texas Instruments TLC591x, nor TLC592x and neither a Maxim6966 would work.
I consider this a strange design decision.
</P>
<P ALIGN="justify">
Another feature I miss, is an 8-segment version of these bar-graphs.
It's just more convenient to work with 8-bit quantities.
Or in the case of bi-colour bar-graphs: 16-bit would be preferable over 10-segment 20-bit units.
Monochromatic, and fixed-colour bar-graphs come in more varied sizes, like 8-segment, 10-segment and even 12-segments sometimes.
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-40606565164062343872021-10-21T16:35:00.001-07:002021-10-21T16:35:09.120-07:00Transistor<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi48lxhSuK3CAvw0Xl9EcRyYFldqk6xOSJxQXZUN6-ahynlGB4eeLnVDxsg3-ZXodn-Bu2lot8TQRzg2oZ0mUbfi6HTYf958srLvrHigNW-R7FJJjPA7RSftdFNQ5Axj9CtPrNhZgOs4SBl/s1374/IMG-8711.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1374" data-original-width="1374" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi48lxhSuK3CAvw0Xl9EcRyYFldqk6xOSJxQXZUN6-ahynlGB4eeLnVDxsg3-ZXodn-Bu2lot8TQRzg2oZ0mUbfi6HTYf958srLvrHigNW-R7FJJjPA7RSftdFNQ5Axj9CtPrNhZgOs4SBl/s600/IMG-8711.jpg"/></a></div>
<P ALIGN="justify">
I am using the <A HREF="https://www.ti.com/product/TLC5928">TLC5928</A> constant current sink driver to light up my <a href="http://thelittleengineerthatcould.blogspot.com/2021/09/led-bars.html">LED bar graphs</a>.
</P>
<P ALIGN="justify">
The neat thing about this part, is that you can set a current (for all 16 outputs) using a reference resistor.
The higher the resistor, the less current the chip will output.
So far so good.
</P>
<P ALIGN="justify">
If you have a LED bar graph that has both GRN and RED LEDs in it, you have a problem, though.
The RED is a lot brighter, and does not need nearly as much current as the GRN one.
I see typically a factor 4x more current for green.
However, the reference resistor sets the current for ALL channels, whether they have a red or a green LED on it.
</P>
<P ALIGN="justify">
So, how to proceed?
Well, I decided to do add pulse-width-modulation for the red LEDs.
I will still drive all channels with the same constant current, but the red LEDs will have their anode voltage (3.3V) interrupted at a few hundred hertz, with a specify duty-cycle. Whereas the green leds will keep seeing their uninterrupted voltage.
</P>
<P ALIGN="justify">
A GPIO pin can never deliver the current required to switch a whole bunch of red LEDs.
So we introduce a little switch, called a Bipolar Junction Transistor of the PNP form.
</P>
<P ALIGN="justify">
When adding a discrete transistor to do perform this PWM job, I also need to add resistors, which makes the design more cluttered.
Fortunately, you can buy pre-biased transistors that already house those resistors along with the transistor.
I have evaluated 3 such pre-biased transistors for this job.
</P>
<P>
<b>DTB114EK</b> (R1 and R2 are 10kΩ)
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiglRUvjQcyJ1COZqD3kJpCgt-QGQ9rf3gKiU-7Z2xLeppvRt0Oba7Y9aAnyy1LBKo1EO2BpNGefYgXEfOCy7L6cJRVTO9YjdIU9xsTvxrFcl-ShKGqKZLAji2xukdgK0tuyNK8gMU7bxv_/s0/Screenshot+from+2021-10-21+16-19-35.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="294" data-original-width="464" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiglRUvjQcyJ1COZqD3kJpCgt-QGQ9rf3gKiU-7Z2xLeppvRt0Oba7Y9aAnyy1LBKo1EO2BpNGefYgXEfOCy7L6cJRVTO9YjdIU9xsTvxrFcl-ShKGqKZLAji2xukdgK0tuyNK8gMU7bxv_/s0/Screenshot+from+2021-10-21+16-19-35.png"/></a></div>
<P>
<b>DTB123TK</b> (R1 is 2.2kΩ)
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZTxdZ_nF_nQiqAAhkUCCPxB4h1-Gz0YeKLUfeDuNN8QMsFEqGidT90AWfo_cC7cMNxxmBHeTJn8ViMdCIwWm-QP95pqYaC9_fJD4HhRRc_6FRuP4iyIgGpvbQvJ0Y0fx-f5NEPh3OZ8wD/s0/Screenshot+from+2021-10-21+16-21-33.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="287" data-original-width="407" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZTxdZ_nF_nQiqAAhkUCCPxB4h1-Gz0YeKLUfeDuNN8QMsFEqGidT90AWfo_cC7cMNxxmBHeTJn8ViMdCIwWm-QP95pqYaC9_fJD4HhRRc_6FRuP4iyIgGpvbQvJ0Y0fx-f5NEPh3OZ8wD/s0/Screenshot+from+2021-10-21+16-21-33.png"/></a></div>
<P>
<b>DTB113ZC</b> (R1 is 1kΩ and R2 is 10kΩ)
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqoEyBlHJcfUIoXKHuM6oXo732nEPJLlSP_3FpsNbxizVCz991AbjrVym8b-4gHp5jwtkJrtnsFEsq4nfUxZZs_nvepbaIbSvp1MEQ_VCR4P80dJg4OiFSNmWnnatnNHKLgHEUVR41rvxL/s0/Screenshot+from+2021-10-21+16-23-20.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="297" data-original-width="449" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqoEyBlHJcfUIoXKHuM6oXo732nEPJLlSP_3FpsNbxizVCz991AbjrVym8b-4gHp5jwtkJrtnsFEsq4nfUxZZs_nvepbaIbSvp1MEQ_VCR4P80dJg4OiFSNmWnnatnNHKLgHEUVR41rvxL/s0/Screenshot+from+2021-10-21+16-23-20.png"/></a></div>
<P ALIGN="justify">
Note that in my case, I have 3.3V at the emitter (pin1) and not GND.
</P>
<P ALIGN="justify">
I've found that a high R1 resistor at the base of the transistor causes the EMITTER->COLLECTOR current to be too limited when the transistor is switched on.
Even when I have a continuous '0' at the base, to switch it on, the current does not get high enough to drive many LEDs.
Hence, between these three, the DTB113ZC with a 1kΩ resistor at the base does the best job for my application.
I find that if I have a bunch of LEDs drawing 109mA in total, and switch that current with the transistor, 90mA makes it through with the DTB113ZC, 79mA makes it through with the DTB123TK and 47mA makes it though with the DTB114EK.
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-33633903277771088812021-10-19T10:33:00.002-07:002021-10-19T10:55:34.618-07:00The state of Electronic Circuit Simulation Software under Ubuntu.<P ALIGN="justify">
Today, I was in need of electronic circuit simulation. Let's see what is available for Ubuntu.
</P>
<P ALIGN="justify">
First I tried ngspice, but that seems to be text based.
</P>
<FONT SIZE=2>
<PRE>
$ ngspice
******
** ngspice-34 : Circuit level simulation program
** The U. C. Berkeley CAD Group
** Copyright 1985-1994, Regents of the University of California.
** Copyright 2001-2020, The ngspice team.
** Please get your ngspice manual from http://ngspice.sourceforge.net/docs.html
** Please file your bug-reports at http://ngspice.sourceforge.net/bugrep.html
** Creation Date: Sat Mar 6 03:53:35 UTC 2021
******
ngspice 1 ->
</PRE>
</FONT>
<P ALIGN="justify">
Ok, install the GUI for it then...
</P>
<FONT SIZE=2>
<PRE>
$ sudo apt install gspiceui
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Package gspiceui is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
</PRE>
</FONT>
<P ALIGN="justify">
Next up: Oregano. I managed to compose a circuit, but when I tried to simulate:
</P>
<FONT SIZE=2>
<PRE>
$ oregano
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX 0x555ee9aeaf10 FALSE
Segmentation fault
</PRE>
</FONT>
<P ALIGN="justify">
Next up: xschem. Again, I managed to draw a schematic, which is done in an awkward way. When I wanted to simulate, I could find no such option in the menus. It seems it cannot?
</P>
<P ALIGN="justify">
Ok, let's move to QUCS. No hit on a package search in Ubuntu, which does not bode well. Ok, let's grab a deb from the archive.
</P>
<FONT SIZE=2>
<PRE>
# dpkg -i qucs_0.0.20.201022-2_amd64.deb
Selecting previously unselected package qucs.
(Reading database ... 281811 files and directories currently installed.)
Preparing to unpack qucs_0.0.20.201022-2_amd64.deb ...
Unpacking qucs (0.0.20.201022-2) ...
dpkg: dependency problems prevent configuration of qucs:
qucs depends on libqt4-qt3support (>= 4:4.5.3); however:
Package libqt4-qt3support is not installed.
qucs depends on libqt4-script (>= 4:4.5.3); however:
Package libqt4-script is not installed.
qucs depends on libqt4-svg (>= 4:4.5.3); however:
Package libqt4-svg is not installed.
qucs depends on libqtcore4 (>= 4:4.7.0~beta1); however:
Package libqtcore4 is not installed.
qucs depends on libqtgui4 (>= 4:4.8.0); however:
Package libqtgui4 is not installed.
dpkg: error processing package qucs (--install):
dependency problems - leaving unconfigured
Processing triggers for libc-bin (2.33-0ubuntu5) ...
Processing triggers for desktop-file-utils (0.26-1ubuntu1) ...
Processing triggers for mailcap (3.68ubuntu1) ...
Processing triggers for gnome-menus (3.36.0-1ubuntu1) ...
Processing triggers for hicolor-icon-theme (0.17-2) ...
Processing triggers for man-db (2.9.4-2) ...
Processing triggers for menu (2.1.47ubuntu4) ...
Errors were encountered while processing:
qucs
root@Workstation:/home/bram/Downloads# apt install libqt4-script libqt4-svg libqtcore4 libqtgui4
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Package libqtcore4 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
</PRE>
</FONT>
<P ALIGN="justify">
Maybe GEDA?
</P>
<FONT SIZE=2>
<PRE>
# apt install geda
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Package geda is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
E: Package 'geda' has no installation candidate
</PRE>
</FONT>
<P ALIGN="justify">
Oh dear... I am about to give up now. I can see now, why CircuitLab manages to charge $399,- per year.
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com1tag:blogger.com,1999:blog-7776021459998532494.post-1112000400235980962021-10-08T20:04:00.001-07:002021-10-12T12:06:47.470-07:00The SMD Hurdle<P ALIGN="justify">
I found that <a href="https://thelittleengineerthatcould.blogspot.com/2021/09/arduino.html">programming microcontrollers</a> and designing electronic circuits is so much more fun than modern software development for PC.
I have really taken to the hobby.
So much so, that I'm beginning to think a pivot is in order.
</P>
<P ALIGN="justify">
When I started mobile game development in feb 2009, I was ahead of the curve.
So far ahead of the curve, that app-store money was easy to come by.
No game engines, no unity available. Everything had to be custom roll-your-own code.
The number of people that knew OpenGL <b>and</b> ObjectiveC was near zero.
It was good to be at the start-point of the democratization of software development.
Fast forward to today, and the market is so crowded, it is impossible to stand out.
</P>
<P ALIGN="justify">
Just as the iPhone opened up a cottage industry of app developers, I think there is a new wave that you can ride, that is not very crowded.
Chinese PCB factories have made electronics design accessible to all.
For $40 dollars or so, you can have your PCB printed manufactured in a small batch.
And if you add a few hundred, you can even get the procurement, and placement of the components on your board, for full service fabrication of your design.
Not bad!
</P>
<P ALIGN="justify">
Hence, the last few weeks, I have been designing electronic circuits using <a href="https://easyeda.com/">EasyEDA</a>.
It's an easy to use, free PCB design tool.
I like it a lot, except for the slow cloud operations that it relies on for many of its operations.
But kudos to them for providing a Linux client for it.
</P>
<P ALIGN="justify">
So far, I have ordered PCB service from both <a href="https://jlcpcb.com">JLCPCB</a> and <a href="https://pcbway.com">PCBWay</a>.
Those are the two biggest players in the PCB market, both located in China.
From JLCPCB I ordered my first design, which was Through-Hole components only, so I could do the assembly myself.
From PCBWay I ordered full service PCB with assembly and component procurement included.
That was quite a bit more expensive. And that order has not been completed yet, as it still waits for component delivery.
The JLCPCB order did arrive already, and is shown below.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIbWw0V4dDhvINrlZQNq2gWNkCG8UwS_fm_9fl_GEXNy8C-0FqWyHSrpg8OA2cbzJWB4H0MQyyuav6J_gom7etW5Q2zwruBiz26RUmbjcQI_a3xMReTaZrW8aqtNpI4JaNjVuSqFNjT14y/s2603/IMG-8517.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1208" data-original-width="2603" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIbWw0V4dDhvINrlZQNq2gWNkCG8UwS_fm_9fl_GEXNy8C-0FqWyHSrpg8OA2cbzJWB4H0MQyyuav6J_gom7etW5Q2zwruBiz26RUmbjcQI_a3xMReTaZrW8aqtNpI4JaNjVuSqFNjT14y/s600/IMG-8517.jpg"/></a></div>
<P ALIGN="justify">
I'll go into the actual product that I am designing, at a later time.
But currently, the design is getting more and more complex.
The second version had SMD components, so I had pcbway do that for me.
</P>
<P ALIGN="justify">
Revision 3 had even more and even smaller components, in a <a href="https://www.ti.com/lit/ml/mpqf124g/mpqf124g.pdf">QFN-24</a> (0.5mm spacing) package even!
And to make matters worse: at both sides of the PCB.
This is because my design is densily integrated and has space constraints, so I needed both sides of the board.
As I was preparing my order for assembly at JLCPCB, the site told me that two-sided SMD assembly was not supported.
I had to pick one side, which they would do for me. Ugh.
</P>
<P ALIGN="justify">
So, I need to reexamine my options.
Would SMD mounting be something I could attempt myself?
I've always backed away from it, as being too much of a hurdle.
</P>
<P ALIGN="justify">
But some makers with SMD DIY <a href="https://youtu.be/NxPWwHUJCqM">videos</a> have convinced me that it must be possible.
So I decided to have a go at it, myself!
Surface mounting tiny little components on a PCB.
</P>
<P ALIGN="justify">
For this, I will be ordering a set of new tools:
</P>
<UL>
<LI>A re-work station, which is just a temperature controlled heat-gun.</LI>
<LI>Solder paste (a mix of metal, solder, flux.)</LI>
<LI>Scraper.</LI>
<LI>Tweezers.</LI>
<LI>Big-ass magnifying glass.</LI>
</UL>
<P ALIGN="justify">
In addition of all this, I must make sure that I order my PCBs with a stencil plate.
This stencil will help me apply the paste to where it is needed.
</P>
<P>
In a good fortune of events, the manufacturer of the <a href="http://www.chipquik.com">leading soldering paste</a> is from Canada.
Nice! No import duties, and fast shipping.
</P>
<P ALIGN="justify">
Anyways, wish me luck!
</P>
<P ALIGN="justify">
Oh no! <b>That is too small!</b>
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv6Fe7dVrqzw0oh5225ltdggcs0x9aIKoJ0_NALFgUl4NB_jr62w9P2D5nst88jJlrbqNIEGyTTAx4_A-wbP3oRBURsie8WWDBfIEK3Cg0wO2gFoN7c2xbGpREK6TCyOgSv8emryjczYlk/s2048/FBY_5T8VcAgkt1r.jpeg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="2048" data-original-width="2048" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv6Fe7dVrqzw0oh5225ltdggcs0x9aIKoJ0_NALFgUl4NB_jr62w9P2D5nst88jJlrbqNIEGyTTAx4_A-wbP3oRBURsie8WWDBfIEK3Cg0wO2gFoN7c2xbGpREK6TCyOgSv8emryjczYlk/s600/FBY_5T8VcAgkt1r.jpeg"/></a></div>Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-10437607977081161182021-09-21T12:33:00.012-07:002021-11-25T11:30:09.795-08:00LED Bars<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuvE6YFs5pb6VVpZ_a4ujSUEloTuEbNM8P-jko8B70t5aiHwPtzwnWX2KnfX0rPljX8zX52XiXYjzQoPH7Ukd0t78mfI631pI9px_rCMzJymNGXuj_Dwa75eHKTNdv7uGXjUqKvradzi21/s1715/unnamed.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1715" data-original-width="1715" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuvE6YFs5pb6VVpZ_a4ujSUEloTuEbNM8P-jko8B70t5aiHwPtzwnWX2KnfX0rPljX8zX52XiXYjzQoPH7Ukd0t78mfI631pI9px_rCMzJymNGXuj_Dwa75eHKTNdv7uGXjUqKvradzi21/s600/unnamed.jpg"/></a></div>
<P ALIGN="justify">
Two LED bar graphs. You would think they would be much alike, but no.
</P>
<P ALIGN="justify">
On the left: LTA-1000Y (2017 Thailand.) On the right: FJB10Y.
</P>
<P ALIGN="justify">
The polarity is reversed. The LTA has anode on the side of the first pin. The FBJ has the cathode on the side of the first pin.
</P>
<P ALIGN="justify">
The obvious difference: face colour grey vs face colour black.
</P>
<P ALIGN="justify">
Light colour is similar, but brightness is much different. I need to use 470 ohm resistor with the LTA, and a 2K ohm resister with the FJB.
</P>
<P ALIGN="justify">
I did some extra research on another convention, for multi-coloured bars. Is RED on top or on the bottom of the bar?:
</P>
<UL>
<LI><A HREF="https://media.digikey.com/pdf/Data%20Sheets/Avago%20PDFs/HDSP-4830_40_50_32_36_HLCP-J100.pdf">AVAGO HDSP-4832</A> has R/R/R/Y/Y/Y/Y/G/G/G with pin 1 as RED anode.</LI>
<LI><A HREF="https://www.kingbrightusa.com/images/catalog/SPEC/DC7G3HWA.pdf">KingBright DC7G3HWA</A> has G/G/G/G/G/G/G/R/R/R with pin 1 as GRN anode.</LI>
<LI><A HREF="https://media.digikey.com/pdf/Data%20Sheets/Fairchild%20PDFs/MV5x164.pdf">Fairchild MV5A164</A> (obsolete) has R/R/R/Y/Y/Y/Y/G/G/G with pin 1 as RED anode.</LI>
<LI><A HREF="https://media.digikey.com/pdf/Data%20Sheets/Fairchild%20PDFs/MV5x164.pdf">Fairchild MV5C164</A> (obsolete) has G/G/G/G/G/G/Y/Y/Y/R with pin 1 as GRN anode.</LI>
<LI><A HREF="http://www.hezkyden.cz/shop/bargraf-10xled/">KYX B10BBGYR</A> has B/G/G/G/G/Y/Y/Y/R/R with pin 1 as BLU anode.</LI>
<LI><A HREF="https://twitter.com/BramStolk/status/1448812313742512161?s=20">MT1025CTF</A> has G/G/G/G/G/Y/Y/Y/R/R with pin 1 as GRN anode. Pin 1 (unmarked) at side that has print.</LI>
<LI><A HREF="https://www.digikey.ca/en/products/detail/sunled/XGMDKVGX10D/13559325">SunLED XGMDKVGX10D</A> has 10+10 bi-colour LEDs to interpolate between GRN to YLW to RED. To use them, 2k Ohm on R and 470 Ohm on G works well. Unfortunately, it is a common-cathode setup, which makes it useless for standard LED drivers.</LI>
<LI>F2510GHR has G/G/G/G/Y/Y/Y/Y/R/R with pin 1 as GRN cathode. It is easy to connect incorrectly. <b>UNLIKE ALL OTHERS, THIS ONE HAS PRODUCT NUMBER PRINTED AT CATHODE SIDE (BUT STILL AT PIN1 SIDE.)</b> Gorgeous colours though, with the yellow being more like amber, A nice looking green that is not very bright, though.</LI>
<LI>F2510HYG has R/R/R/R/Y/Y/Y/G/G/G with pin 1 as RED anode.</LI>
</UL>
<P ALIGN="justify">
Some 8 segment led bars:
</P>
<UL>
<LI>F2010RG is R/R/G/G/G/G/G/G with pin1 as red anode.</LI>
<LI>KYX-B08GOR is G/G/G/G/G/G/R/R with pin1 as grn anode.</LI>
</UL>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-57127018716853608792021-09-20T16:38:00.004-07:002021-11-28T14:45:22.525-08:00Arduino<P ALIGN="justify">
Last year, I did a project with the <a href="https://store.arduino.cc/products/arduino-micro">Arduino Micro</a> kit.
This is an ATmega32U4 microcontroller.
</P>
<P ALIGN="justify">
With it, I built a USB input device, with knobs, to tune my noise fields for Ring Miner.
</P>
<iframe width="560" height="315" src="https://www.youtube.com/embed/IUk6w59Ov2E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<P ALIGN="justify">
In that project, I was simultaneously writing USB HID data, reading turn knobs, and writing OLED displays.
In order to avoid stalls I had to <a href="https://arduino.stackexchange.com/a/75483/65894">modify</a> the standard lib so I could skip writing USB data if there was no space available in the buffer, which is what happens when the PC is not reading the USB HID device.
</P>
<P ALIGN="justify">
I have recently picked up the Arduino again.
This time to see if I can steer LED bar graphs with it.
I noticed that out of the box, Ubuntu's arduino IDE will not run.
You need to <a href="https://bugs.launchpad.net/ubuntu/+source/arduino/+bug/1916278/comments/8">patch</a> a library before it will run.
</P>
<P ALIGN="justify">
I have been learning on how to drive LEDs with a constant current shift register.
I think I will end up using the <a href="https://www.ti.com/lit/ds/symlink/tlc5917.pdf?HQS=dis-dk-null-digikeymode-dsf-pf-null-wwe&ts=1632180932823&ref_url=https%253A%252F%252Fwww.ti.com%252Fgeneral%252Fdocs%252Fsuppproductinfo.tsp%253FdistId%253D10%2526gotoUrl%253Dhttps%253A%252F%252Fwww.ti.com%252Flit%252Fgpn%252Ftlc5917">TLC5917IN</a> chip.
Unfortunately, it is only 8 bit, I would have preferred 10 bits, but it was available in-stock, and affordable.
</P>
<P ALIGN="justify">
The simplicity of micro controllers is refreshing, in this age of super complexity.
Close to the metal, and straightforward.
</P>
<P ALIGN="justify">
When coding for micro controllers, use <B>static PROGMEM const</B> qualifier for your data that you want to reside in ROM, instead of RAM.
</P>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0tag:blogger.com,1999:blog-7776021459998532494.post-42147642756073043342021-07-04T12:16:00.000-07:002021-07-04T12:16:00.402-07:00Catching a fall (procedurally.)
<P ALIGN="justify">
I have been doing a lot of <a href="https://twitter.com/BramStolk/status/1411443263127494656?s=20">procedural animation</a>, lately.
Making a humanoid walk, and swing a torch at spiders.
</P>
<P ALIGN="justify">
I also needed a proper way to catch a fall, with the legs.
Because I already had the Inverse Kinematics sorted, I just needed to shift the pelvis down, and up, after a fall.
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqAr9nR-aszG-p7CTZQ5cHtIbUGQizE3Gc8kPCzkcebNiH96f-vUcI_g7UZozNU1ncx4r-D_SG7W4_A2mx5dXHUAGtnubQKVnsxAWwPjNppNmDqwZW-ltm5xqbJFsuDo7tplTW0EDQfYbH/s0/optim.gif" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="490" data-original-width="646" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqAr9nR-aszG-p7CTZQ5cHtIbUGQizE3Gc8kPCzkcebNiH96f-vUcI_g7UZozNU1ncx4r-D_SG7W4_A2mx5dXHUAGtnubQKVnsxAWwPjNppNmDqwZW-ltm5xqbJFsuDo7tplTW0EDQfYbH/s0/optim.gif"/></a></div>
<P ALIGN="justify">
To do this convincingly, I need to drop down hard at the start, then ease at the nadir, and ease again on the way back to the zenith.
For this, piecewise functions come to the rescue.
I ended up using <a href="https://www.wolframalpha.com/input/?i=plot+piecewise%5B%7B+%7B+cos%28pi%2F2%2Bx%2F2%29%2C+x%3Cpi+%7D%2C+%7B+%28cos%28x%29-1%29%2F2%2C+x%3Epi+%7D+%7D%5D+for+x%3D0+to+2*pi+">this</a>:
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKm7YRrsAuyGQBofeKg2QP6p9p6waU_Ntiupu9Dia8w0lg8QKBzh2XGTpIMIseVNDBZB1J36G3D2JtqCZo-0kGgd9HFCcwjijM6l-OEi4KwKnv6PefG3uBTEXfc8E1mKDU5P0hfdgy1Hmj/s0/catchfall.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="404" data-original-width="460" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKm7YRrsAuyGQBofeKg2QP6p9p6waU_Ntiupu9Dia8w0lg8QKBzh2XGTpIMIseVNDBZB1J36G3D2JtqCZo-0kGgd9HFCcwjijM6l-OEi4KwKnv6PefG3uBTEXfc8E1mKDU5P0hfdgy1Hmj/s0/catchfall.png"/></a></div>
Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com1tag:blogger.com,1999:blog-7776021459998532494.post-51412831022868736862021-06-21T18:34:00.006-07:002021-06-22T20:22:56.934-07:00Field Of View<P ALIGN="justify">
Computer monitors come in different aspect ratios.
From the old school <a href="https://en.wikipedia.org/wiki/Iiyama_Vision_Master_Pro_17_computer_monitor">4:3</a> to the ridiculous <a href="https://www.pcmag.com/reviews/samsung-chg90-49-inch-curved-ultrawide-monitor">32:9</a>.
</P>
<P ALIGN="justify">
In my 3D games, I have to choose a Field-Of-View for the camera. Wide angle, or narrow angle views?
To do this, the convention is to set a fixed vertical field of view, and then adopt the horizontal field of view that falls out of it, based on the image aspect ratio.
I use this for all my 3D games: set the vertical F.o.V.
</P>
<CENTER>
<IMG WIDTH=656 HEIGHT=656 SRC="https://stolk.org/diagrams/fov.svg" />
</CENTER>
<P ALIGN="justify">
Fixing the Vertical Field of View, means that users on 4:3 monitors see less of the world, and users on ultra wide screen see more of the world.
This could pose an unfair advantage.
</P>
<P ALIGN="justify">
An additional problem is that ultra wide aspect ratios lead to ultra wide angle views, which lead to a lot of distorted shapes in the corners of the screen.
</P>
<P ALIGN="justify">
But fixing the Horizontal Field of View instead, would mean that users on wide-screen would see less of the world (at top and bottom parts of screen.)
This made me wonder... what if I were to fix the angle for the diagonal field instead? Fixed for all users.
And then let the Horizontal/Vertical angles fall out of this.
</P>
<P ALIGN="justify">
Definitely worth an experiment!
So let's do some trigonometry!
</P>
<P ALIGN="justify">
Problem: given a fixed angle for the diagonal field of view... what are the corresponding Vertical and Horizontal fields of view?
</P>
<CENTER>
<IMG WIDTH=656 HEIGHT=656 SRC="https://stolk.org/diagrams/fov_problem.svg" />
</CENTER>
<P ALIGN="justify">
Given the fixed diagonal field of view angle <b>α</b>, and a given image height <b>h</b>, and image diagonal <b>d</b>, we need merely two equations to derive the vertical field of view angle <b>β</b>.
</P>
<P ALIGN="justify">
And with that angle <b>β</b> we can set up our projection matrix the usual way.
</P>
<P ALIGN="justify">
When we do all this, we go from extremist views (with fixed vertical FoV) like these:
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0-6efCpWif_Qpi9A7tL4aN09vfNsy1ZVex1v4Gvd60nibS6sbjFexr1fPVsJMXt3LdIQnY20DIEnZFwUZGGucripmM0cXmI_PgZm5A12xd9H8YNSyhhx03CH8SdM4bnGp6jHKFdOKLipB/s820/Screenshot+from+2021-06-21+18-03-44.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="200" data-original-height="655" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0-6efCpWif_Qpi9A7tL4aN09vfNsy1ZVex1v4Gvd60nibS6sbjFexr1fPVsJMXt3LdIQnY20DIEnZFwUZGGucripmM0cXmI_PgZm5A12xd9H8YNSyhhx03CH8SdM4bnGp6jHKFdOKLipB/s320/Screenshot+from+2021-06-21+18-03-44.png"/></a></div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2GjjWR8moQn_3AYB2zZYK6U01DCNqTnT2ba-ZaBrOK9n4Uy4L2POi8dpQK0GkFuqGT0BE2HuK2ogm_5AaferIXS3BuA92yqiIw9yv7RafosRMdI9GcLZZMI8aza7dcaDOWrZ7XrqsFyNR/s1452/Screenshot+from+2021-06-21+18-06-43.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="200" data-original-height="655" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2GjjWR8moQn_3AYB2zZYK6U01DCNqTnT2ba-ZaBrOK9n4Uy4L2POi8dpQK0GkFuqGT0BE2HuK2ogm_5AaferIXS3BuA92yqiIw9yv7RafosRMdI9GcLZZMI8aza7dcaDOWrZ7XrqsFyNR/s320/Screenshot+from+2021-06-21+18-06-43.png"/></a></div>
<P ALIGN="justify">
...to more moderate views (with fixed diagonal FoV) like the ones below. Note that the view angles change less than in the case above, between aspect ratios.
The narrow aspect ratio does not show that much less on left/right, and for what it loses on the sides, it wins a little on top/bottom.
I think this approach is a keeper!
</P>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNNnyRC41ak0qv4rnPsofOnFIPh5tJ2bMSVDoanj8l059I1eDMDWS4-wBJ1M5x_7YdupJv5fEYAPq3RpwBoacSGeD2MiwmSRn2yZ8GrW_huKU8tzNGv0wXwhBXBKxkGW9NcLql8V46UTdN/s820/Screenshot+from+2021-06-21+18-22-17.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" heght="200" data-original-height="655" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNNnyRC41ak0qv4rnPsofOnFIPh5tJ2bMSVDoanj8l059I1eDMDWS4-wBJ1M5x_7YdupJv5fEYAPq3RpwBoacSGeD2MiwmSRn2yZ8GrW_huKU8tzNGv0wXwhBXBKxkGW9NcLql8V46UTdN/s320/Screenshot+from+2021-06-21+18-22-17.png"/></a></div><div class="separator" style="clear: both;"><a href="https://1.bp.blogspot.com/-x1XsiMDSeL9w/YNE8LTFDfpI/AAAAAAAAHQ4/04RqyUOPCvESPRqDcQnKmItLlmi67_BogCLcBGAsYHQ/s1452/Screenshot%2Bfrom%2B2021-06-21%2B18-23-32.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="200" data-original-height="655" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisH6JDbVhBc6fEcb9cVXp3E8eTaHS8bMBB4vcRqBLwiVN8X_ZOwJQjjP7i0P5jqsdTI9okPPGRAYvHRod9DnguqXfKdIDrt3LRy_CLGACbHuV8R73iBIzBbaX1LPww6z5YqSrMnwZ2EsVG/s320/Screenshot+from+2021-06-21+18-23-32.png"/></a></div>
For completeness, the code, which is trivial:
<FONT SIZE=2>
<PRE>
float vertical_fov_from_diagonal_fov( float a, float w, float h )
{
const float d = sqrtf(w*w + h*h);
const float m = d / ( 2 * tanf( a / 2 ) );
const float b = 2 * atanf( h / (2*m) );
return b;
}
</PRE>
</FONT>Bramhttp://www.blogger.com/profile/07666511303597120943noreply@blogger.com0