Aziz Bench

Calcul PWM : fréquence et résolution

Choisissez la puce et la fréquence voulue : vous voyez combien de bits de résolution du rapport cyclique vous obtenez, la fréquence exacte, les valeurs du diviseur ou du timer et le code pour Arduino, ESPHome et les SDK.

Résolution du rapport cyclique
13bits
8 192 pas à 5 kHz
Fréquence obtenue
5 kHzexacte
Plus petit pas
24,4 ns0,0122 % de la période
Diviseur
1,953horloge APB, 80 MHz
Signal
état haut 100 µspériode 200 µs
Puce et logiciel
Logiciel

Arduino-ESP32 3.x cadence le PWM sur le quartz pour toutes les puces sauf l’ESP32 d’origine, ce qui limite la résolution. ESPHome choisit la résolution lui-même.

Signal
Hz

En hertz : 5000 correspond à 5 kHz.

%

Réglages et code

Horloge et diviseurHorloge APB à 80 MHz, diviseur 1,953 (div_param 500), 13 bits ; le timer tourne à 5 kHz.
Valeur à écrire50 % = 4 096 sur 8 192. Écrivez 8 192 pour une sortie toujours à l’état haut, 0 pour une sortie toujours à l’état bas.
Plage possibleÀ 5 kHz : de 1 à 13 bits. À 13 bits : de 0,119 Hz à 9,7656 kHz.
Réglages partagésL’ESP32 a 16 canaux PWM et 8 timers : les canaux d’un même timer partagent fréquence et résolution.

Code

Remplacez la broche par la vôtre : les valeurs correspondent au résultat ci-dessus.

Arduino-ESP32 3.x
const int PWM_PIN = 4;          // GPIO
const uint32_t PWM_FREQ = 5000;     // Hz
const uint8_t PWM_RES = 13;        // bit: 0–8192

void setup() {
  ledcAttach(PWM_PIN, PWM_FREQ, PWM_RES);
  ledcWrite(PWM_PIN, 4096);        // 50 %
}

void loop() {}
ESPHome
output:
  - platform: ledc
    pin: GPIO4
    id: pwm_out
    frequency: 5kHz

light:
  - platform: monochromatic
    output: pwm_out
    name: "LED"
ESP-IDF
#include "driver/ledc.h"
#include "esp_err.h"

void app_main(void)
{
    ledc_timer_config_t timer = {
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .duty_resolution = LEDC_TIMER_13_BIT,
        .timer_num = LEDC_TIMER_0,
        .freq_hz = 5000,
        .clk_cfg = LEDC_AUTO_CLK,
    };
    ESP_ERROR_CHECK(ledc_timer_config(&timer));

    ledc_channel_config_t channel = {
        .gpio_num = 4,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .channel = LEDC_CHANNEL_0,
        .timer_sel = LEDC_TIMER_0,
        .duty = 4096,              // 50 %
        .hpoint = 0,
    };
    ESP_ERROR_CHECK(ledc_channel_config(&channel));
}

Résolution maximale aux fréquences courantes

FréquenceRésolution
50 Hz20 bits
490 Hz17 bits
1 kHz16 bits
5 kHz13 bits
20 kHz11 bits
25 kHz11 bits
40 kHz10 bits
100 kHz9 bits
1 MHz6 bits

Conseils

Arduino-ESP32 3.x : ledcAttach(pin, freq, resolution) remplace ledcSetup() et ledcAttachPin() de la version 2.x, et ledcWrite() prend la broche, pas le canal.

L’ESP32 a deux groupes de 8 canaux : high-speed, qui applique tout de suite le nouveau rapport cyclique, et low-speed. Arduino-ESP32 remplit d’abord le groupe high-speed.

Chaque canal prend sa fréquence sur l’un des 8 timers : deux sorties à des fréquences différentes demandent deux timers.

Pour les LED, utilisez au moins 1,25 kHz : l’IEEE 1789 juge à faible risque un PWM tout allumé / tout éteint à partir de 1250 Hz, et pour les personnes sensibles à partir d’environ 3 kHz.

Texte prêt à coller dans un forum ou une issue.

Pourquoi fréquence et résolution sont liées

Un périphérique PWM compte des impulsions d’horloge : le compteur fixe la période, la valeur de comparaison la durée pendant laquelle la sortie reste à l’état haut. Avec n bits de résolution, le compteur a besoin de 2^n impulsions par période, donc la fréquence maximale est l’horloge divisée par 2^n. À 80 MHz, 8 bits permettent jusqu’à 312,5 kHz, 13 bits jusqu’à 9,77 kHz et 1 bit jusqu’à 40 MHz, avec un rapport cyclique bloqué à 50 %.

f(max) = f(horloge) / 2^bits
f = f(horloge) / (diviseur × 2^bits)

Le diviseur a aussi une limite haute, si bien que les basses fréquences demandent plus de bits, pas moins : sur un ESP32-S3 avec l’horloge de 80 MHz, 50 Hz demande au moins 11 bits.

ESP32 : le périphérique LEDC

Toutes les puces ESP32 produisent le PWM avec le périphérique LEDC : un diviseur à 8 bits fractionnaires, de 1 à environ 1024, et un compteur jusqu’à 20 bits sur les ESP32, C5, C6, H2 et P4, 14 bits sur les S2, S3 et C3. L’horloge peut être l’APB à 80 MHz (une sortie de la PLL sur les puces récentes, 96 MHz sur le H2), le quartz (40 MHz ; 32 MHz sur le H2, 40 ou 48 MHz sur le C5), un oscillateur RC interne ou, sur l’ESP32 et le S2, le REF_TICK à 1 MHz.

Arduino-ESP32 3.x cadence le PWM sur le quartz pour toutes les puces sauf l’ESP32 d’origine. La fréquence maximale baisse alors à chaque résolution, de moitié là où un quartz de 40 MHz remplace une horloge de 80 MHz : sur un ESP32-S3, 5 kHz donne 12 bits au lieu de 13. Appeler ledcSetClockSource(LEDC_AUTO_CLK) avant ledcAttach() laisse le pilote choisir l’horloge la plus rapide ; cette fonction existe depuis Arduino-ESP32 3.0.5. ESPHome utilise l’horloge APB quand elle existe et choisit la résolution lui-même.

Raspberry Pi Pico : RP2040 et RP2350

Chaque tranche PWM a un compteur 16 bits qui repart à zéro après TOP et un diviseur de 1 à 255 + 15/16 par pas de 1/16. La fréquence est l’horloge système divisée par (TOP + 1) et par le diviseur, puis encore par 2 en mode phase-correct. Comme TOP peut prendre n’importe quelle valeur, le Pico atteint exactement la plupart des fréquences : à 125 MHz, 25 kHz correspond à TOP 4999 avec un diviseur de 1, soit environ 12,3 bits.

Arduino Uno et Nano : les timers de l’ATmega328P

Timer0 et Timer2 sont sur 8 bits, Timer1 sur 16 bits, chacun avec une série fixe de prédiviseurs N. La fréquence dépend de N et de TOP : horloge / (N × (TOP + 1)) en fast PWM, horloge / (2 × N × TOP) en phase-correct. analogWrite() les laisse au prédiviseur 64 : 976,6 Hz sur les broches 5 et 6, 490,2 Hz sur les broches 3, 9, 10 et 11. Pour d’autres fréquences, le Timer1 avec TOP dans ICR1 garde les deux broches et jusqu’à 16 bits : un signal de 25 kHz pour un ventilateur sur la broche 9 correspond à ICR1 = 639 sans prédiviseur.

ESP8266

L’ESP8266 n’a pas de PWM matériel : le core Arduino et ESPHome le produisent par logiciel, de 100 Hz à 40 kHz dans le core Arduino, avec une plage de 255 par défaut. D’après la documentation du core, les fréquences élevées occupent le processeur.

Quelle fréquence pour quel usage

UsageFréquencePourquoi
Variation d’intensité de LED1,25 kHz ou plusL’IEEE 1789 juge à faible risque de scintillement un PWM tout allumé / tout éteint à partir de 1250 Hz
Servo de modélisme50 Hz, impulsions de 1 à 2 msUne impulsion toutes les 20 ms, dont la durée fixe l’angle
Ventilateur PC 4 fils25 kHz (21–28 kHz)Spécification Intel des ventilateurs PWM à 4 fils
Moteur CCenviron 20 kHz ou plusAu-dessus du seuil d’audition, mais vérifiez la limite du driver
Buzzer passifLa fréquence de la note, 50 %La fréquence donne la hauteur du son

Valeurs par défaut de chaque plateforme

PlateformeanalogWrite() par défautRésolution maximaleHorloge du PWM
ESP32 (Arduino-ESP32 3.x)1 kHz, 8 bits20 bitsAPB 80 MHz ou REF_TICK 1 MHz (AUTO)
ESP32-S2, S3, C3 (Arduino-ESP32 3.x)1 kHz, 8 bits14 bitsXTAL 40 MHz par défaut
ESP32-C5, C6, P4 (Arduino-ESP32 3.x)1 kHz, 8 bits20 bitsXTAL 40 MHz par défaut (C5 : 40 ou 48 MHz)
ESP32-H2 (Arduino-ESP32 3.x)1 kHz, 8 bits20 bitsXTAL 32 MHz par défaut
RP2040, RP2350 (Arduino-Pico)1 kHz, plage 25516 bitsHorloge système : 200 MHz (Pico), 150 MHz (Pico 2)
ATmega328P (Uno, Nano)490 Hz (broches 3, 9, 10, 11), 976,6 Hz (broches 5, 6), 8 bits16 bits (Timer1)16 MHz avec prédiviseur 64
ESP8266 (core Arduino 3.x)1 kHz, plage 255Plage jusqu’à 65535PWM logiciel

Sources : pilote LEDC et fichiers de capacités des SoC d’ESP-IDF (release 5.5), esp32-hal-ledc.c et documentation de l’API LEDC d’Arduino-ESP32 3.x, composants ledc, rp2040_pwm et esp8266_pwm d’ESPHome, datasheet du RP2040 et hardware_pwm du pico-sdk, wiring_analog.cpp d’Arduino-Pico, datasheet Microchip de l’ATmega328P et core AVR d’Arduino, référence du core Arduino pour ESP8266, spécification Intel des ventilateurs PWM à 4 fils, IEEE 1789-2015 selon la synthèse du département de l’Énergie des États-Unis, bibliothèque Servo d’Arduino.

Questions fréquentes

Quelle est la fréquence PWM maximale sur l’ESP32 ?

40 MHz, avec 1 bit de résolution et un rapport cyclique fixé à 50 % : l’horloge de 80 MHz divisée par 2. Pour une variation d’intensité exploitable, 8 bits permettent jusqu’à 312,5 kHz et 10 bits jusqu’à 78,1 kHz. Avec Arduino-ESP32 3.x sur les puces autres que l’ESP32 d’origine, l’horloge du quartz, utilisée par défaut, abaisse ces valeurs (de moitié sur les puces dotées d’un quartz de 40 MHz et d’une horloge APB ou PLL de 80 MHz), sauf si vous appelez ledcSetClockSource(LEDC_AUTO_CLK), disponible depuis la version 3.0.5.

Pourquoi ledcAttach() échoue-t-il avec « requested frequency and duty resolution can not be achieved » ?

Parce que le diviseur doit rester entre 1 et environ 1024. Si la fréquence est trop haute pour les bits demandés, baissez la résolution. Si elle est trop basse, augmentez la résolution : avec moins de bits, il faut un diviseur plus grand. Le calculateur affiche la plage valide pour les deux.

Quelle fréquence PWM pour un ventilateur PC à 4 broches ?

25 kHz : la spécification d’Intel accepte de 21 à 28 kHz. Un ESP32 à 25 kHz atteint 11 bits avec l’horloge de 80 MHz ; un Arduino Uno sort 25 kHz sur la broche 9 avec le Timer1 et ICR1 = 639. Commandez la ligne PWM du ventilateur avec une sortie à drain ouvert ou un transistor, car c’est le ventilateur lui-même qui la tire vers le haut.

Comment piloter un servo en PWM avec l’ESP32 ?

À 50 Hz avec 14 bits, un pas vaut environ 1,2 µs, assez fin pour un servo : 1,5 ms correspond à 1229, 1 ms à 819 et 2 ms à 1638. Dans ESPHome, reliez une sortie ledc à 50 Hz au composant servo ; avec Arduino, vous pouvez aussi utiliser une bibliothèque comme ESP32Servo.

Pourquoi la fréquence PWM des broches 5 et 6 de l’Arduino Uno est-elle différente ?

Les broches 5 et 6 utilisent le Timer0 en fast PWM (976,6 Hz), les autres le Timer1 et le Timer2 en phase-correct (490,2 Hz). Le Timer0 cadence aussi millis() : ne changez son prédiviseur que si vous acceptez des millis() et delay() faussés.

Quelle résolution PWM pour des LED ?

Avec 8 bits (256 pas), la variation se fait par à-coups à faible luminosité, là où l’œil remarque le plus les petits changements ; avec 12 bits ou plus et une courbe gamma, les fondus sont fluides. Gardez la fréquence à 1,25 kHz ou plus pour limiter le scintillement.

Les deux sorties d’une tranche PWM du Pico peuvent-elles avoir des fréquences différentes ?

Non : A et B partagent le compteur, donc la même fréquence et le même TOP, et seul le rapport cyclique peut changer. Si vous avez besoin de fréquences différentes, prenez des broches sur des tranches différentes.