Sigma-Delta a PWM
Vylepšení PWM.

Motivace.

Moderní jednočipy někdy obsahují DA převodník, ale v některých situacích potřebujeme výstup analogového signálu a tento převodník chybí. Nabízí se použít časovač a generovat jím signál s pulsně šířkovou modulací (PWM) a ten pak analově filtrovat dolní propustí. Jenže pro rozumnou frekvenci buzení časovače a rovněž rozumnou maximální frekvenci výstupního signálu bývá rozlišení PWM poměrně malé - např. 256 kroků, tedy 8 bitů. To vadí především tam, kde je potřeba udržovat na výstupu přesné a stabilní napětí.

Jak to funguje.

Můžeme to zkusit vylepšit. Půjčíme si na to techniku Sigma-Delta převodníku. Spíš než dlouhý popis je lépe se podívat na tento kousek kódu:

static const int INPUT_BIT_RANGE = 16;
static const unsigned SIGMA_MASK = (1u << (INPUT_BIT_RANGE + 0)) - 1u;
static const unsigned SIGNED_OFFEST = (1u << (INPUT_BIT_RANGE - 1));
// Předpokládá se na vstupu signed int o šířce INPUT_BIT_RANGE
// přičemž 0 na vstupu odpovídá maxpwm / 2 na výstupu
static unsigned pwm_sd (const int input, const int maxpwm) {
static unsigned sigma = 0; // podstatné je, že proměnná je statická
const unsigned sample = (input + SIGNED_OFFEST) * maxpwm;
sigma &= SIGMA_MASK; // v podstatě se odečte hodnota PWM
sigma += sample; // integrace prostým součtem
return sigma >> INPUT_BIT_RANGE;
}
// Takto se počítá obyčejná PWM modulace
static unsigned pwm_pure (const int input, const int maxpwm) {
const unsigned sample = (input + SIGNED_OFFEST) * maxpwm;
return sample >> INPUT_BIT_RANGE;
}

Můžete si vyzkoušet.

Jednoduchý prográmek je napsán v Qt.

pwm.png

I z tohoto obrázku je vidět, že odstup signál/šum je na nízkých frekvencích opravdu o dost nižší. Pokud si chcete pohrát, verze pro WebAssembly je zde.

Pozn.:

  1. Zřejmě to nebude fungovat ve všech prohlížečích (technologie je zatím dost neodladěná).
  2. Je to pomalejší než nativní aplikace a i ta je dost pomalá - vykresluje poměrně dost bodů ve frekvenční oblasti. Takže po změně parametru je potřeba několik sekund počkat než se to překreslí.
  3. Horní graf (časová závislost) je možné kolečkem myši zoomovat a myší tahat po widgetu.
  4. Spodní graf je pevný.
  5. Menu ve verzi pro WebAssembly nic nedělá. Zatím není podpora pro vlákna.

Rozlišení PWM je volitelné, vzorkovací frekvence PWM 65.536 kHz. Není to moc realistické, pokud uvážíme, že s touto frekvencí se opakuje výpočet hodnoty, ale lze použít třeba DMA a vzorky předpočítat do bufferu a lze změnit parametry tak, aby to vyhovovalo pro dané použití. Graf časového průběhu lze zvětšit a pak je vidět dithering použité metody. Je dobré si uvědomit, že metoda potlačuje především nízké frekvence, vyšší naopak zdůrazňuje, takže je pak nutné to někde dolní propustí uříznout. To je u obyčejné PWM ovšem potřeba také. Ale lze lépe zvolit kompromis mezi rozlišením a dynamikou, je to vidět především na frekvencích o hodně menších než vzorkovací frekvence. Tady je právě jádro použitelnosti metody. Systémy s poměrně malou dynamikou, ale vysokým rozlišením, kde bude použita dolní propust na relativně nízké frekvenci. Nicméně bylo to vyzkoušeno i pro audio aplikaci, kde je šum při rozlišení PWM 256 kroků docela slyšitelný, tato metoda jej umí dost účinně potlačit. Nakonec Sigma-Delta modulace se dost používá právě zde.

Ke stažení.

Zdrojáky pro Qt5 jsou zde.