Hi, just a quick note to talk about a code update.

But first… I’d like to present to you: A straight line:

Do you see it? That picture shows a straight line. Or at least, some parts which, when added together, make a straight line.

Anyway, there were a couple things bugging me ever since the Noctigon KR4 came out:

- The low modes weren’t low enough. They were bright, and had big gaps between, so the bottom end of the ramp kinda sucked.
- The FET made an audible tone during thermal regulation.

The low-modes issue happens because the linear power channel’s steps were too big. It made about 2000 lm and divided those into 1024 steps, so each step was about 2 lm. I could fix it by increasing the number of steps, but then the FET noise issue would get worse.

The FET noise issue happens because the pulses aren’t fast enough. With 1024 PWM steps, that means instead of running at the usual 16 kHz, it ran instead at 4 kHz… and people can hear that pretty easily. I could fix it by speeding it up, but then the low modes would be worse — 8 lm apart instead of 2 lm.

*sigh*

But then a few days ago I was looking through the attiny1634 reference manual, and I noticed something which could solve both problems. And not just on KR4, but on several other models too — KR1, some D4v2, DT8, maybe K1, and possibly more.

Basically, instead of using PWM alone (pulse width modulation), it combines PWM and PFM (pulse frequency modulation).

Here’s how the KR4’s ramp looks, on a logarithmic scale, if I calculate the closest possible steps to what it should be. It starts at 1/1024, repeats that a few times, then does 2/1024, repeats that, then 3/1024, and so on. The bottom end has big wide steps:

The top line (blue) is the raw PWM value from 1 to 1023. The bottom line (orange) represents how bright it appears by eye.

To fix it, the idea is simple. Let’s say you want the smoothest ramp possible, but you can only use integers. For some nice round numbers, let’s say the hardware can have up to 100 levels of PWM… like, 1/100 for moon, then 2/100, 3/100, and so on, up to 99/100 and then 100/100 for full power.

That gets us 100 different levels. But the bottom few have very visible “stair steps” between them. Going from 1/100 to 2/100 *doubles* the brightness in a single step, and then going up to 3/100 adds another 50% in one step, and then beyond that each step appears smoother and smoother.

This can be solved by changing the number on the bottom. For example…

- Ramping from 1/100 to 2/100 can be done in 50 steps: 1/100, 1/99, 1/98, 1/97, … all the way to 1/51. Then 2/100.
- Ramping from 2/100 to 3/100 can be done in 33 steps: 2/100, 2/99, 2/98, 2/97, … all the way to 2/67. Then 3/100.
- Ramping from 3/100 to 4/100 can be done in 25 steps: 3/100, 3/99, 3/98, … 3/76, then 4/100.

See the pattern?

This gets us a really smooth ramp at the low end. By changing the numerator slowly (pulse width), and changing the denominator quickly (pulse frequency), it can reach many steps in-between the steps.

So the bottom end is fixed!

But it still has the noise issue on high modes. So how about we also make it start at a slow speed for low levels, and increase the speed for high levels? That way, it has precision at the bottom of the ramp, and extra speed at the top.

After combining both of those things, the ramp tables look like this:

Top (orange) line: Denominator — the length of each cycle.

Middle (blue) line: Numerator — the width of each pulse.

Bottom (green) line: How bright the result looks by eye (pulse width divided by pulse frequency).

Much better now. Divide one zig-zaggy line by another zig-zaggy line, and the result is … a smooth line.

(To make some other stuff easier, I set the “fast” point about halfway up the ramp, and everything above that runs at the fastest speed. So the weird shapes stop halfway up.)

If I combine both images into one graph, the difference is pretty easy to see:

However, there’s still a problem. The lowest brightness in both cases is still too high — about 2 lumens. So maybe instead of using 1024 at the bottom end, it should use a bigger number. This should give it a lower starting point.

Here are a few options, all together on one graph:

- 512 step cycle: minimum of 4 lumens
- 1024 step cycle: minimum of 2 lumens
- 2048 step cycle: minimum of 1 lumen
- 4096 step cycle: minimum of 0.5 lumens

Even the lowest one is still a bit high though… and the real KR4 has 2 power channels, not just 1. So how about bumping it all the way up to 16384 levels at the bottom? Here’s how that looks:

(apologies for the visual brightness stopping at the end of the first channel… it should keep going up when the second channel turns on)

… and that’s the same as the graph I started with, at the top of this post. It just has things in a logarithmic scale instead of a linear scale.

During use, the ramp looks pretty close to visually linear. It starts at about 0.2 lm at the bottom end, then increases smoothly all the way to 4000 lm. So it makes a straight line… when graphed on a perceptual scale.

It sure doesn’t look like a straight line when the individual parts are graphed, though.

Math is weird.

Anyway, long story short… It was bugging me, so I fixed it.