13б. Buzzer: active and passive, notes on a timer, a non-blocking melody
In section 13а the timer gave a servo the pulse width at a constant
frequency. A buzzer needs the opposite: the meaning is in the
frequency, and the duty cycle stays near one half. Here is how an
active buzzer differs from a passive one, how to switch it through a
transistor, how to get PSC and ARR of TIM1 at 72 MHz from a note with
an error of hundredths of a cent, how to play a melody from the SysTick
interrupt without stopping main, and why the duty cycle is a poor
volume knob.
Sources: RM0008 (DocID13902 Rev 17): PWM, the OCxPE and ARPE preload,
the UG bit, p. 386; the MOE bit, p. 358; pin modes in CRH, p. 171.
DocID13587 Rev 17 (STM32F103x8/xB): PA8 is TIM1_CH1 with 5 V tolerance,
p. 31; FT means 5 V tolerant, p. 33; the maximum pin current is 25 mA, p. 37.
The project has no documents on buzzers: note frequencies are equal
temperament from A4 = 440 Hz and are computed in the run. All numbers
below come from a run of the code _verify/buzzer13c/buzzer13c.c on a
computer (gcc 12.2.0) with our own model of TIM1 in Python 3.11; the
firmware is built by armclang 6.24 for the Cortex-M3.
What it is called in the documentation
Original Meaning active buzzer active buzzer: the generator is inside, it needs only a level passive buzzer, piezo transducer passive buzzer, piezo transducer: the controller supplies the frequency magnetic buzzer electromagnetic buzzer: a coil, it needs a diode equal temperament equal temperament: a semitone is a factor of 2^(1/12) cent cent — a hundredth of a semitone prescaler ( PSC)timer prescaler auto-reload register ( ARR)auto-reload register: the counting period duty cycle duty cycle update event update event: the end of a period, the buffers move into the working registers preload ( ARPE,OCxPE)preload: a new value takes effect from the next period flyback diode flyback diode: suppresses the coil spike non-blocking non-blocking: the code does not wait in a loop
13б.1 Active and passive: how to tell them apart
An active buzzer carries a generator inside: apply a level and it beeps at its own frequency, remove it and it goes quiet. A plain output is enough for the controller, like for an LED, but you cannot play a melody on it: there is only one frequency.
A passive buzzer is just a piezo disc or a coil: at a constant level it is silent, the sound comes only from an alternating signal of the right frequency. It has to be fed a PWM square from a timer — but then any note is possible.
To tell them apart on the bench: apply a constant voltage to the buzzer through a resistor. An active one beeps, a passive one only clicks at the moment of connection. Another sign — an active one often has a board with parts underneath and a "+" mark, a passive one is a bare disc.
The firmware of this section has both: a passive one on PA8 (TIM1_CH1),
an active one on PB0 — a short beep at start-up, without waiting in code.
13б.2 Connection: a transistor and a diode
Better not to take the buzzer current from the pin: the buzzer goes through an NPN transistor, the pin drives the base through a resistor, and the buzzer sits between the supply plus and the collector. Then the pin gives only the base current, and the buzzer can run from 5 V, above the 3.3 V logic. An electromagnetic buzzer (a coil) needs a flyback diode in parallel: at switch-off the coil throws out a voltage spike, and without the diode it hits the transistor. A piezo transducer needs no diode.
PA8 is a 5 V tolerant pin (FT, DocID13587, p. 31 and 33), but tolerance only says the pin survives 5 V at its input. The pin current is limited to 25 mA (p. 37) — and that is the absolute maximum, not a working value. Resistor values and currents were not computed here — they depend on the buzzer and the transistor, take them from the documents on your parts.
The timer pin is an alternate-function push-pull output, nibble 0xB in
CRH (RM0008, p. 171); TIM1 also needs the MOE bit (p. 358), otherwise
the output stays silent while the counter runs (section 13.5):
static void tim1_init(void)
{
GPIOA->CRH = (GPIOA->CRH & ~0xFu) | 0xBu; /* PA8 — TIM1_CH1, push-pull, 50 МГц */
TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE; /* ШИМ 1, буфер CCR1 */
TIM1->CCER = TIM_CCER_CC1E;
TIM1->BDTR = TIM_BDTR_MOE; /* у TIM1 без MOE выход молчит (13.5) */
TIM1->CCR1 = 0;
TIM1->CR1 = TIM_CR1_ARPE; /* буфер ARR */
TIM1->EGR = TIM_EGR_UG;
TIM1->CR1 |= TIM_CR1_CEN;
}
13б.3 Notes: from A4 = 440 Hz to PSC and ARR
The frequency of the note with MIDI number n in equal temperament is
440 × 2^((n − 69) / 12) Hz: A4 is 69, C4 is 60, a semitone is a factor of
2^(1/12). The code holds a table of one octave (the eighth) in hundredths
of a hertz, and below it halves the frequency for every octave, without
floating point:
uint32_t bz_ticks(uint8_t note, uint32_t tim_hz)
{
if (note < BZ_LOW || note > BZ_HIGH)
return 0; /* пауза и всё вне таблицы — тишина, без деления */
uint32_t f = f8_chz[note % 12u];
uint32_t sh = 9u - note / 12u; /* сколько октав вниз от восьмой */
uint64_t num = ((uint64_t)tim_hz * 100u) << sh;
return (uint32_t)((num + f / 2u) / f); /* f_tim / f_ноты, округлено */
}
bz_ticks gives the note period in timer ticks: 72 MHz / f. For A4 that
is 163 636 ticks — it does not fit into a 16-bit ARR, so bz_timing
takes the smallest divider that makes it fit and rounds the period:
int bz_timing(uint32_t ticks, bz_tim_t *t)
{
if (ticks < 2u || (ticks - 1u) >> 16 > 0xFFFFu) {
t->ccr = 0; /* CCR = 0 — выход в нуле, звука нет */
return 0;
}
uint32_t d = ((ticks - 1u) >> 16) + 1u; /* наименьший делитель, при котором ARR влезает в 16 бит */
uint32_t per = (ticks + d / 2u) / d; /* период в отсчётах счётчика, округлён */
t->psc = (uint16_t)(d - 1u);
t->arr = (uint16_t)(per - 1u);
t->ccr = (uint16_t)(per / 2u); /* меандр: половина периода */
return 1;
}
The run for the notes of the tune and the first-octave C (TIM1 counts from 72 MHz):
| Note | Exact, Hz | PSC |
ARR |
CCR |
Result, Hz | Error, cent |
|---|---|---|---|---|---|---|
| C4 | 261.63 | 4 | 55 039 | 27 520 | 261.628 | +0.0155 |
| D4 | 293.66 | 3 | 61 293 | 30 647 | 293.667 | +0.0107 |
| E4 | 329.63 | 3 | 54 606 | 27 303 | 329.628 | +0.0027 |
| G4 | 392.00 | 2 | 61 224 | 30 612 | 391.997 | +0.0057 |
| A4 | 440.00 | 2 | 54 544 | 27 272 | 440.004 | +0.0144 |
| B4 | 493.88 | 2 | 48 593 | 24 297 | 493.888 | +0.0169 |
| C5 | 523.25 | 2 | 45 866 | 22 933 | 523.252 | +0.0029 |
| D5 | 587.33 | 1 | 61 294 | 30 647 | 587.324 | −0.0175 |
The whole table from C0 (16.35 Hz) to B8 (7902.13 Hz) is 108 notes: the
worst error is 0.0882 cent at B8, and CCR is exactly half the period
everywhere. The divider grows towards low notes: C0 has PSC = 67, and
from C#6 (1108.73 Hz) PSC = 0 is enough — at 72 MHz a 16-bit count
without a divider gives no lower than 1098.6 Hz. A rest and numbers
outside the table (0, 11, 120) give 0 ticks — silence, without division.
Try it in the app: Lab → bench "Buzzer".
13б.4 Accuracy: own divider versus a 1 MHz count
The timer is often set to 1 MHz (PSC = 71) and ARR = 1 000 000 / f is
written. The step of such a count is 1 µs, and on high notes the period
becomes short and the rounding noticeable:
| Note | ARR |
Result, Hz | Error, cent |
|---|---|---|---|
| A4 | 2272 | 439.947 | −0.21 |
| C7 | 477 | 2092.050 | −0.79 |
| C8 | 238 | 4184.100 | −0.79 |
| B8 | 126 | 7874.016 | −6.17 |
From C4 to B8 the worst error is 6.17 cents at B8. The smallest divider
of 13б.3 keeps all 108 notes within 0.0882 cent. The example "The C
major scale" in the lab rounds the frequency to whole hertz and writes
ARR at a 1 MHz count: the worst note C4 is 262 Hz instead of 261.63, an
error of +2.84 cents. The "1 kHz" tone of the example "A 1 kHz tone on
TIM1" is not a note: the nearest is B5, and it is 21.3 cents above it.
13б.5 A melody without blocking
A melody is an array of steps (note, duration in ms), a rest is note 0.
The player bz_tick is called once per 1 ms from the SysTick interrupt;
it counts the step time itself and says when to change the note. At the
end of each note there is a gap of silence, otherwise two equal notes in
a row merge into one:
int bz_tick(bz_player_t *p, uint8_t *note)
{
if (!p->on)
return BZ_NONE;
if (p->i >= p->n) {
if (!p->loop) {
p->on = 0;
*note = BZ_REST;
return BZ_END; /* мелодия кончилась: тишина */
}
p->i = 0;
}
const bz_step_t *s = &p->song[p->i];
uint8_t want = s->note;
if (want != BZ_REST && p->t + p->gap >= s->ms)
want = BZ_REST; /* хвост ноты — зазор, чтобы две одинаковые не слились */
if (++p->t >= s->ms) {
p->t = 0; /* шаг кончился: со следующей мс — новый */
p->i++;
}
if (want == p->cur)
return BZ_NONE; /* таймер уже играет то, что нужно */
p->cur = want;
*note = want;
return BZ_NOTE;
}
In the firmware the interrupt drives the player, and main is free — it
blinks an LED by the millisecond counter without stopping:
void SysTick_Handler(void)
{
uint8_t note;
ms++;
if (bz_tick(&pl, ¬e) != BZ_NONE)
tone_set(note);
if (beep_left && --beep_left == 0u)
GPIOB->BSRR = GPIO_BSRR_BR0; /* активный: время вышло — «0» */
}
static void tone_set(uint8_t note)
{
bz_tim_t t;
if (!bz_timing(bz_ticks(note, TIM_HZ), &t)) {
TIM1->CCR1 = 0; /* пауза: выход в нуле, ARR не трогаем */
return;
}
TIM1->PSC = t.psc; /* все три — в буферы: вступят вместе */
TIM1->ARR = t.arr; /* на ближайшем обновлении, без обрезанного периода */
TIM1->CCR1 = t.ccr;
}
New PSC, ARR and CCR are written into the buffers (ARPE and
OCxPE, RM0008, p. 386) and take effect together at the nearest update —
so the sound of a note starts not at once but, in the model, up to
1.902 ms after the write. The tune of 12 steps (the same as in the bench
example "A melody from a note table") with a 20 ms gap plays in 3500 ms:
23 writes to the timer, 11 notes, the durations differ from the given
ones (minus the gap) by no more than 2.29 ms. Without the gap there are
12 writes and 10 notes: two A4 of 150 ms in a row merged into one A4 of
300 ms.
13б.6 Volume and duty cycle
It is tempting to set the volume by the duty cycle: CCR below half —
quieter. But a 50 % square is the strongest at the fundamental, and a
smaller duty not only weakens it but also adds the second harmonic — the
sound becomes thinner and shriller. The run from the Fourier series of
the square:
| Duty | CCR (A4) |
Fundamental, rel. to 50 % | Second harmonic |
|---|---|---|---|
| 50 % | 27 272 | 1.00 | 0.0000 |
| 25 % | 13 636 | 0.71 | 0.3183 |
| 10 % | 5454 | 0.31 | 0.1871 |
| 5 % | 2727 | 0.16 | 0.0984 |
The fundamental of a square is proportional to sin(π·D): at 5 % there is
0.16 of the 50 % level left. The bench example "Error: a 5 % duty —
quiet" — CCR = 50 at ARR = 999 — gives the same 0.16. Change an even
volume by the buzzer supply or by the choice of the buzzer itself, and
leave the duty at 50 %.
13б.7 Pitfalls
A rest in the frequency table — and the controller falls over. A
tone in hertz without a check: 1000000 / hz at hz = 0. On a computer
such a process is killed by a division exception (exit code 136).
bz_ticks returns 0 for a rest before any division, and tone_set sets
CCR1 = 0 — silence.
A note out of range is silent or plays the wrong pitch. A number below 12 or above 119 is not in the table and gives silence; without the check the octave shift would go out of bounds.
A forgotten prescaler. PSC = 0 instead of 71 at ARR = 2271: the
timer counts at 72 MHz, and "440 Hz" turns into 31 690 Hz — the ear does
not hear it (the bench example "Error: PSC = 0 — above 20 kHz").
Clicks and torn notes. Without preload a new ARR takes effect at
once: if the counter has already gone further, it counts up to 65 535 and
only then wraps — an extra 2.731 ms at PSC = 2 and 3.641 ms at
PSC = 3. In the run of 10 loops of the tune without a gap: with preload
not a single bent period, without it — 7 stretched and 24 shortened, the
worst by 2.731 ms.
Two equal notes sound like one. No gap between notes — see 13б.5: A4 and A4 merged.
The melody stops the program. Notes through delays in main: while
it plays, buttons and sensors are not polled. The player is in the
SysTick interrupt, main is free.
An active buzzer on PWM. An active one has its own generator (in the bench model — 2.4 kHz): PWM at its input switches it on and off, and on the bench there is crackle instead of a clean tone. It needs a plain output, level "1".
13б.8 Summary
- An active buzzer has the generator inside and needs a level; for a passive one the timer supplies the frequency, a 50 % square.
- The buzzer goes through a transistor; an electromagnetic one needs a
flyback diode; PA8 is
TIM1_CH1, nibble 0xB, TIM1 needs theMOEbit. - A note is 440 × 2^((n − 69) / 12) Hz; at 72 MHz the smallest divider
keeps the 108 notes C0…B8 within 0.0882 cent;
PSC= 0 is enough from C#6. - A 1 MHz count gives up to 6.17 cents of error at B8, rounding to whole hertz — up to 2.84 cents at C4.
- A melody is a table (note, ms), the player runs every 1 ms from SysTick, a 20 ms gap; the 12-step tune takes 3500 ms, 23 timer writes, a note start shifts by up to 1.902 ms.
- Volume by the duty cycle gives 0.16 of full at 5 % and extra
harmonics; the
ARPE/OCxPEpreload removes torn periods.
Full sources
buzzer13c.h — notes, timer timing, melody steps and the player.
/* buzzer13c.h — раздел 13б: ноты и мелодия для пассивного зуммера без регистров.
* Ноты — номера MIDI (69 — A4 = 440 Гц, 60 — C4), 0 — пауза. Частоты — равномерная темперация.
* bz_ticks и bz_timing переводят ноту в PSC/ARR/CCR таймера, плеер bz_tick вызывают раз в 1 мс
* (в прошивке fw13c.c — из SysTick, в стенде host13c.c — в цикле), он говорит, когда сменить ноту. */
#ifndef BUZZER13C_H
#define BUZZER13C_H
#include <stdint.h>
#define BZ_REST 0u /* пауза: таймер молчит, деления нет */
#define BZ_LOW 12u /* C0, 16,35 Гц — ниже таблицы нет */
#define BZ_HIGH 119u /* B8, 7902 Гц — последняя нота таблицы */
/* ноты мелодии из стенда лаборатории */
#define D4 62u
#define E4 64u
#define G4 67u
#define A4 69u
#define B4 71u
#define C5 72u
#define D5 74u
typedef struct {
uint16_t psc, arr, ccr; /* значения для TIM1: частота = f_tim / ((PSC + 1)(ARR + 1)) */
} bz_tim_t;
uint32_t bz_ticks(uint8_t note, uint32_t tim_hz); /* период ноты в тактах таймера; 0 — пауза или вне таблицы */
int bz_timing(uint32_t ticks, bz_tim_t *t); /* PSC, ARR и CCR = половина периода; 0 — тишина */
uint16_t bz_ccr(uint16_t arr, uint8_t pct); /* CCR для заполнения pct % */
/* ── мелодия: шаги (нота, длительность) ─────────────────────────────── */
typedef struct {
uint8_t note; /* MIDI или BZ_REST */
uint16_t ms; /* длительность шага с паузой-зазором */
} bz_step_t;
enum { BZ_NONE, BZ_NOTE, BZ_END }; /* что вернул bz_tick */
typedef struct {
const bz_step_t *song;
uint16_t n, i; /* шагов, текущий шаг */
uint16_t t; /* мс от начала шага */
uint8_t gap; /* тишина в конце каждой ноты, мс */
uint8_t loop, on;
uint8_t cur; /* что сейчас стоит на таймере; 0xFF — ещё ничего */
} bz_player_t;
void bz_play(bz_player_t *p, const bz_step_t *song, uint16_t n, uint8_t gap_ms, uint8_t loop);
int bz_tick(bz_player_t *p, uint8_t *note); /* раз в 1 мс; BZ_NOTE — поставить *note */
#define BZ_DEMO_N 12u
extern const bz_step_t bz_demo[BZ_DEMO_N]; /* мотив из стенда лаборатории */
#endif
buzzer13c.c — note frequencies, PSC/ARR, the melody player.
/* buzzer13c.c — раздел 13б: ноты в PSC/ARR и плеер мелодии без регистров. */
#include "buzzer13c.h"
/* Октава 8 (MIDI 108…119) в сотых долях герца: 440 × 2^((n − 69) / 12) × 100, округлено.
* Нижние октавы — делением пополам: на октаву ниже частота вдвое меньше. */
static const uint32_t f8_chz[12] = {
418601u, 443492u, 469864u, 497803u, 527404u, 558765u, /* C8 C#8 D8 D#8 E8 F8 */
591991u, 627193u, 664488u, 704000u, 745862u, 790213u, /* F#8 G8 G#8 A8 A#8 B8 */
};
uint32_t bz_ticks(uint8_t note, uint32_t tim_hz)
{
if (note < BZ_LOW || note > BZ_HIGH)
return 0; /* пауза и всё вне таблицы — тишина, без деления */
uint32_t f = f8_chz[note % 12u];
uint32_t sh = 9u - note / 12u; /* сколько октав вниз от восьмой */
uint64_t num = ((uint64_t)tim_hz * 100u) << sh;
return (uint32_t)((num + f / 2u) / f); /* f_tim / f_ноты, округлено */
}
int bz_timing(uint32_t ticks, bz_tim_t *t)
{
if (ticks < 2u || (ticks - 1u) >> 16 > 0xFFFFu) {
t->ccr = 0; /* CCR = 0 — выход в нуле, звука нет */
return 0;
}
uint32_t d = ((ticks - 1u) >> 16) + 1u; /* наименьший делитель, при котором ARR влезает в 16 бит */
uint32_t per = (ticks + d / 2u) / d; /* период в отсчётах счётчика, округлён */
t->psc = (uint16_t)(d - 1u);
t->arr = (uint16_t)(per - 1u);
t->ccr = (uint16_t)(per / 2u); /* меандр: половина периода */
return 1;
}
uint16_t bz_ccr(uint16_t arr, uint8_t pct)
{
return (uint16_t)(((uint32_t)arr + 1u) * pct / 100u);
}
void bz_play(bz_player_t *p, const bz_step_t *song, uint16_t n, uint8_t gap_ms, uint8_t loop)
{
*p = (bz_player_t){0};
p->song = song;
p->n = n;
p->gap = gap_ms;
p->loop = loop;
p->on = n > 0u;
p->cur = 0xFFu;
}
int bz_tick(bz_player_t *p, uint8_t *note)
{
if (!p->on)
return BZ_NONE;
if (p->i >= p->n) {
if (!p->loop) {
p->on = 0;
*note = BZ_REST;
return BZ_END; /* мелодия кончилась: тишина */
}
p->i = 0;
}
const bz_step_t *s = &p->song[p->i];
uint8_t want = s->note;
if (want != BZ_REST && p->t + p->gap >= s->ms)
want = BZ_REST; /* хвост ноты — зазор, чтобы две одинаковые не слились */
if (++p->t >= s->ms) {
p->t = 0; /* шаг кончился: со следующей мс — новый */
p->i++;
}
if (want == p->cur)
return BZ_NONE; /* таймер уже играет то, что нужно */
p->cur = want;
*note = want;
return BZ_NOTE;
}
const bz_step_t bz_demo[BZ_DEMO_N] = {
{E4, 200}, {A4, 200}, {B4, 200}, {D5, 400}, {C5, 200}, {A4, 200},
{G4, 200}, {B4, 400}, {A4, 150}, {A4, 150}, {D4, 600}, {BZ_REST, 600},
};
fw13c.c — STM32F103 firmware: TIM1 on PA8, an active buzzer on PB0, the player in SysTick.
/* fw13c.c — раздел 13б: зуммеры на STM32F103 (BluePill), 72 МГц.
* Пассивный зуммер — через транзистор на PA8 (TIM1_CH1): ШИМ-меандр с частотой ноты.
* Активный зуммер — через транзистор на PB0: свой генератор, включается уровнем «1».
* SysTick раз в 1 мс ведёт плеер мелодии (buzzer13c.c) и отсчитывает писк активного;
* основной цикл свободен — мигает светодиодом PC13 по счётчику миллисекунд.
* Тактирование до 72 МГц — как в разделе 6 (здесь не повторяется); TIM1 на APB2 считает от 72 МГц. */
#include "stm32f10x.h"
#include "buzzer13c.h"
#define TIM_HZ 72000000u
_Static_assert(TIM_HZ / 1000u - 1u == 71999u, "SysTick: LOAD = 71999 — прерывание раз в 1 мс");
static bz_player_t pl;
static volatile uint32_t ms;
static volatile uint32_t beep_left;
static void tone_set(uint8_t note)
{
bz_tim_t t;
if (!bz_timing(bz_ticks(note, TIM_HZ), &t)) {
TIM1->CCR1 = 0; /* пауза: выход в нуле, ARR не трогаем */
return;
}
TIM1->PSC = t.psc; /* все три — в буферы: вступят вместе */
TIM1->ARR = t.arr; /* на ближайшем обновлении, без обрезанного периода */
TIM1->CCR1 = t.ccr;
}
void SysTick_Handler(void)
{
uint8_t note;
ms++;
if (bz_tick(&pl, ¬e) != BZ_NONE)
tone_set(note);
if (beep_left && --beep_left == 0u)
GPIOB->BSRR = GPIO_BSRR_BR0; /* активный: время вышло — «0» */
}
static void beep(uint32_t len_ms) /* активный зуммер: писк без ожидания */
{
__disable_irq();
beep_left = len_ms;
GPIOB->BSRR = GPIO_BSRR_BS0;
__enable_irq();
}
static void tim1_init(void)
{
GPIOA->CRH = (GPIOA->CRH & ~0xFu) | 0xBu; /* PA8 — TIM1_CH1, push-pull, 50 МГц */
TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE; /* ШИМ 1, буфер CCR1 */
TIM1->CCER = TIM_CCER_CC1E;
TIM1->BDTR = TIM_BDTR_MOE; /* у TIM1 без MOE выход молчит (13.5) */
TIM1->CCR1 = 0;
TIM1->CR1 = TIM_CR1_ARPE; /* буфер ARR */
TIM1->EGR = TIM_EGR_UG;
TIM1->CR1 |= TIM_CR1_CEN;
}
int main(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_TIM1EN;
GPIOB->CRL = (GPIOB->CRL & ~0xFu) | 0x2u; /* PB0 — выход push-pull 2 МГц, к базе транзистора */
GPIOC->CRH = (GPIOC->CRH & ~(0xFu << 20)) | 0x2u << 20; /* PC13 — светодиод платы */
tim1_init();
bz_play(&pl, bz_demo, BZ_DEMO_N, 20u, 1u); /* зазор 20 мс, по кругу */
SysTick_Config(TIM_HZ / 1000u);
beep(100u);
uint32_t next = 0;
for (;;) {
if ((int32_t)(ms - next) >= 0) { /* не ждём: просто смотрим на часы */
next += 500u;
GPIOC->ODR ^= 1u << 13;
}
}
}
Next: section 13в "16-channel PWM PCA9685 over I2C: servos and LEDs without the microcontroller's timers" — sixteen PWM channels over two I2C wires, when there are not enough timers for all the servos and LEDs.