Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> VHDL

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

La modulation de largeur d'impulsion (PWM) transforme une broche FPGA numérique en un contrôleur analogique puissant. En commutant l'alimentation à haute vitesse, le PWM délivre le courant moyen exact dont un dispositif a besoin, sans jamais générer une vraie tension analogique.

Les applications typiques du PWM incluent la sortie audio pour haut-parleurs, la gradation de LED, et le contrôle du couple de moteurs à induction tels que les servomoteurs, ventilateurs d'ordinateur, pompes, et moteurs brushless DC pour véhicules électriques.

Voir aussi : Contrôleur de servo RC utilisant PWM depuis une broche FPGA

Comment fonctionne le PWM

Quand une alimentation est basculée entre 100 % et 0 % à une fréquence élevée, le courant moyenné dans le temps vu par la charge est directement proportionnel à la fraction de temps où l'alimentation est active. Le diagramme suivant illustre le principe :

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

Cycle de travail (Duty Cycle)

Le cycle de travail définit combien de temps la sortie PWM reste haute pendant chaque période. Exprimé en pourcentage, il est calculé à partir de la valeur du compteur binaire :

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

Dans une implémentation VHDL, nous traitons le cycle de travail comme un entier non signé, nous donnant la résolution complète du compteur PWM. Un cycle de travail de 0 % éteint la sortie en permanence, tandis qu'un cycle de travail de 100 % la maintient continuellement active. La résolution atteignable est déterminée par la largeur du compteur.

Pour convertir la valeur binaire du cycle de travail en pourcentage, utilisez :

\mathit{duty\_cycle\_percentage} = \frac{\mathit{commanded\_duty\_cycle} * 100}{2^\mathit{pwm\_bits} - 1}

Fréquence PWM

La fréquence PWM est l'inverse de la période :

\mathit{pwm\_freq} = \frac{1}{\mathit{pwm\_period}}

Le choix de la bonne fréquence dépend du dispositif cible. Pour les LED, quelques centaines de hertz suffisent pour éviter le scintillement visible. Les moteurs brushless DC, en revanche, fonctionnent généralement dans la gamme des dizaines de kilohertz ; une fréquence trop basse peut produire des vibrations mécaniques, tandis qu'une fréquence trop élevée gaspille de l'énergie.

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

Comme les commutateurs MOSFET sont plus lents que la logique FPGA, faire fonctionner le PWM trop vite peut faire passer le transistor dans un état partiellement conducteur, ce qui dissipe de la chaleur supplémentaire.

Module générateur PWM

Voici une implémentation VHDL générique d'un contrôleur PWM qui peut être instancié avec n'importe quelle largeur de compteur et facteur de division d'horloge.

Déclaration d'entité

 entity pwm is generic ( pwm_bits : integer; clk_cnt_len : positive := 1 ); port ( clk : in std_logic; rst : in std_logic; duty_cycle : in unsigned(pwm_bits - 1 downto 0); pwm_out : out std_logic ); end pwm; 

Les ports clk et rst fournissent un contrôle synchrone. L'entrée duty_cycle a une largeur définie par pwm_bits, donc la résolution du compteur est directement configurable. Le signal pwm_out est routé vers la broche FPGA qui pilote la grille du MOSFET.

Signaux internes

 signal pwm_cnt : unsigned(pwm_bits - 1 downto 0); signal clk_cnt : integer range 0 to clk_cnt_len - 1; 

Le compteur pwm_cnt miroite la largeur du cycle de travail. Le compteur clk_cnt implémente un diviseur d'horloge optionnel ; régler clk_cnt_len à 1 désactive le diviseur et supprime la logique associée.

Processus diviseur d'horloge

 CLK_CNT_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then clk_cnt <= 0; else if clk_cnt < clk_cnt_len - 1 then clk_cnt <= clk_cnt + 1; else clk_cnt <= 0; end if; end if; end if; end process; 

Avec le clk_cnt_len = 1 par défaut, les outils de synthèse élimineront ce processus automatiquement.

Processus de sortie PWM

 PWM_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then pwm_cnt <= (others => '0'); pwm_out <= '0'; else if clk_cnt_len = 1 or clk_cnt = 0 then pwm_cnt <= pwm_cnt + 1; pwm_out <= '0'; if pwm_cnt = unsigned(to_signed(-2, pwm_cnt'length)) then pwm_cnt <= (others => '0'); end if; if pwm_cnt < duty_cycle then pwm_out <= '1'; end if; end if; end if; end if; end process; 

Le compteur s'incrémente seulement quand clk_cnt est zéro, limitant effectivement la fréquence PWM. La condition qui réinitialise pwm_cnt à sa valeur la plus haute moins deux garantit qu'un cycle de travail de 100 % est atteignable.

\mathit{pwm\_hz} = \frac{\mathit{clk\_hz}}{(2^\mathit{pwm\_bits} - 1) * \mathit{clk\_cnt\_len}}

Conception de niveau supérieur

Pour démontrer le contrôleur PWM, la conception pilote la LED de mise sous tension sur une carte FPGA Lattice iCEstick. L'oscillateur 12 MHz de la carte alimente un compteur qui pilote l'intensité de la LED en motif de dent de scie.

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

Déclaration d'entité

 entity pwm_led is generic ( pwm_bits : integer := 8; cnt_bits : integer := 25; clk_cnt_len : positive := 47 ); port ( clk : in std_logic; rst_n : in std_logic; led_1 : out std_logic; led_2 : out std_logic; led_3 : out std_logic; led_4 : out std_logic; led_5 : out std_logic ); end pwm_led; 

L'horloge 12 MHz et les génériques choisis produisent une fréquence PWM d'environ 1 kHz :
\frac{12e6}{(2^8 - 1) * 47} \approx 1 \text{ kHz}

Le générique cnt_bits pilote un compteur en dent de scie de 25 bits qui contrôle le cycle de travail de la LED. Sa période est d'environ 2,8 Hz :

\frac{2^{\mathit{cnt\_bits}}}{\mathit{clk\_hz}} = \frac{2^{25}}{12e6} \approx 2.8 \text{ Hz}

Seule la LED 5 est utilisée ; les autres LED sont tirées à bas pour éviter l'éclairage parasite.

Signaux internes et câblage

 architecture str of pwm_led is signal rst : std_logic; signal cnt : unsigned(cnt_bits - 1 downto 0); signal pwm_out : std_logic; alias duty_cycle is cnt(cnt'high downto cnt'length - pwm_bits); begin led_1 <= '0'; led_2 <= '0'; led_3 <= '0'; led_4 <= '0'; led_5 <= pwm_out; 

Le signal rst est une version synchronisée, non inversée du reset externe. L'alias duty_cycle mappe les bits de poids fort de cnt vers le contrôleur PWM.

Instanciations de modules

 RESET : entity work.reset(rtl) port map ( clk => clk, rst_n => rst_n, rst => rst ); PWM : entity work.pwm(rtl) generic map ( pwm_bits => pwm_bits, clk_cnt_len => clk_cnt_len ) port map ( clk => clk, rst => rst, duty_cycle => duty_cycle, pwm_out => pwm_out ); COUNTER : entity work.counter(rtl) generic map ( counter_bits => cnt'length ) port map ( clk => clk, rst => rst, count_enable => '1', counter => cnt ); 

Simulation

Les génériques facilitent l'accélération de la simulation. En réduisant cnt_bits et clk_cnt_len, nous pouvons observer des cycles PWM complets en quelques microsecondes au lieu de plusieurs secondes.

Instanciation du banc de test :

 DUT : entity work.pwm_led(str) generic map ( pwm_bits => 8, cnt_bits => 16, clk_cnt_len => 1 ); 

La forme d'onde dans ModelSim montre un compteur en dent de scie pilotant la luminosité de la LED. Une brève impulsion « on » apparaît au sommet de chaque cycle quand le cycle de travail atteint sa valeur maximale.

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

Implémentation FPGA

Après synthèse avec iCEcube2, la conception ne consomme que 5 % des 64 LUTs disponibles sur la partie ice40hx1ktq144 :

 Resource Usage Report for pwm_led Mapping to part: ice40hx1ktq144 Cell usage: GND 3 uses SB_CARRY 31 uses SB_DFF 5 uses SB_DFFSR 39 uses SB_GB 1 use VCC 3 uses SB_LUT4 64 uses I/O ports: 7 I/O primitives: 7 SB_GB_IO 1 use SB_IO 6 uses I/O Register bits: 0 Register bits not including I/Os: 44 (3%) Total load per clock: pwm_led|clk: 1 @S |Mapping Summary: Total LUTs: 64 (5%) 

La programmation du FPGA via USB avec le programmeur Diamond standalone était simple. L'animation LED résultante montre une rampe de luminosité douce suivie d'un bref assombrissement avant que le cycle ne se répète.

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

LED respirante avec cycle de travail en onde sinusoïdale

Remplacer le compteur en dent de scie par une table de recherche d'onde sinusoïdale produit un effet « respirant » naturel, couramment vu sur les LED de notification.

Implémenter un contrôleur PWM en VHDL : Conception, simulation et démo FPGA

Dans un article à venir, nous montrerons comment construire un générateur d'onde sinusoïdale utilisant la RAM bloc et l'intégrer dans la conception pwm_led.

Lisez le prochain article : Comment créer un effet LED respirant en utilisant une onde sinusoïdale stockée dans la RAM bloc

Voir aussi : Contrôleur de servo RC utilisant PWM depuis une broche FPGA

VHDL

  1. Contrôleur de puissance PWM : construction d'un driver de lampe à modulation de largeur d'impulsion
  2. Créer des listes de chaînes en VHDL : Bonnes pratiques et exemple
  3. Créer un banc de test piloté par Tcl pour un module verrou code VHDL
  4. Terminer proprement une simulation de banc de test VHDL
  5. Générer des nombres aléatoires en VHDL : De l'uniforme à OSVVM
  6. Conception d'un tampon circulaire VHDL robuste en mémoire bloc
  7. Comment construire un testbench auto-vérifiant en VHDL - Guide pratique
  8. Implémentation d'une liste chainée dynamique en VHDL avec types protégés et pointeurs d'accès
  9. Guide étape par étape pour charger des condensateurs en toute sécurité et efficacement