While looking at the power LED on my notebook when it is in standby, I started to think about a way to implement the typical “breathing” animation. The standard way involves having an interrupt which gets called a few dozen times a second setting (much higher frequency) PWM value on the LED.

Wouldn’t it be nice, if one could just configure the hardware and the LED would perform the pulsing sequence without need for any software intervention?

Basic function

In acoustics, there is a concept called “beat”.

In short, if we try to sum two sinusoids with frequencies \(f_1\) and \(f_2\), which are relatively close to each other, the resulting waveform is going to pulse at \(f_1 - f_2\) with frequency \(\frac{f_1 + f_2}{2}\).

1000kHz + 1001kHz

I am not going to perform any rigorous proving here, but addition is fairly similar to performing the AND operation and square waves are similar to sinusoids, so we can intuit that if we manage to do AND on two square waves of different frequencies, we should get a similar effect.

Ok, producing a square wave of a given frequency on a pin should be trivial, and the simplest way to perform the ANDing is probably the following:

There are four possible states in this circuit, and the LED is going to be lit only iff the top pin (say \(b_1\)) is high and the bottom (\(b_2\)) is low. So this circuit basically performs \(b_1 \wedge \neg{b_2} \)

Note: The LED is going to get reverse biased, do not forget to check whether it can handle whatever the reverse voltage will be.

Anyway, let’s actually verify that it does what it should:

Just by looking at how the waveforms re-align in time is enough to tell that the brightness waveform is going to be a triangle wave. At first this does not sound like something that would be similar to breathing, but it looks reasonably good. The fact that human eyes do not sense brightness linearly probably helps significantly.

Adding PWM to the mix

Now we have the basic pulsing animation done, but only the pulsing frequency is controllable. However, if there is PWM on the output pins available, it can be used to make the animation much more customizable.

Simulator

To get some intuition for getting the configuration right, I hacked together a D3-driven interactive simulator:



Also note how the peak brightness changes, this needs to be compensated for by changing the series resistor’s value.

Conclusion

There are obviously some disadvantages to this method — especially the fact that it needs two entire timers. On the other hand, modern MCUs tend to end up with a ton of unused timers anyway in a lot of applications.