Régler la fréquence PWM à 25 kHz


5

Je peux actuellement fixé quatre broches PWM à environ 31   kHz avec le code suivant:

void setup() 
{ 
    TCCR1B = TCCR1B & B11111000 | B00000001; // Set PWM frequency for D9 & D10: 
    pinMode(pwmPin9, OUTPUT); // Sets the pin as output 
    pinMode(pwmPin10, OUTPUT); // Sets the pin as output 


    TCCR2B = TCCR2B & B11111000 | B00000001; // Set PWM for D3 & D11 
    pinMode(pwmPin3, OUTPUT); // Sets the pin as output 
    pinMode(pwmPin11, OUTPUT); // Sets the pin as output 
} 

J'ai trouvé cette configuration quelque part, mais je ne sais pas comment je peux définir ces quatre broches PWM à environ 25   kHz à la place. Comment est-ce possible?

+3

Comprenez-vous le fonctionnement des minuteurs AVR? 24 juin. 162016-06-24 01:04:33

+2

Voir [ma page sur les timers] (http://www.gammon.com.au/timers). 24 juin. 162016-06-24 01:06:55

+1

@ IgnacioVazquez-Abrams Je ne suis pas familier et j'ai besoin de régler ces quatre broches à environ 25kHz au début. J'ai hâte de finir un projet et je serais ravi de recevoir de l'aide. Le code que j'ai défini à 31kHz. Puis-je le modifier à 25kHz? Les moteurs à courant continu exigent que la fréquence. 24 juin. 162016-06-24 01:08:57

+1

@NickGammon Merci, mais je n'ai vraiment pas assez de temps pour les étudier en ce moment. Pourriez-vous me fournir la partie code pour configurer 25kHz.Im lost 24 juin. 162016-06-24 01:12:01

  0

Pourquoi quatre broches? Est-ce qu'ils vont tous avoir des cycles de travail différents? Pourquoi pas une épingle et l'envoyer à quatre endroits différents? 24 juin. 162016-06-24 02:24:25

  0

'Je peux actuellement définir quatre broches pwm à environ 31kHz avec le code suivant' - J'ai juste essayé votre code et il n'a rien sorti. 24 juin. 162016-06-24 06:06:53

+2

J'ai besoin de régler leur régime exact pour que leurs cycles d'utilisation soient légèrement différents. Comment est-il possible de régler 2 broches seulement à 25kHz? 24 juin. 162016-06-24 07:26:58

  0

Ce code peut être facilement adapté pour régler la fréquence sur 31400, 3920, 490, 123 ou 30,6 Hz. Les autres fréquences ne seraient pas si simples et impliqueront probablement un changement dans la résolution de la sortie PWM. Pouvez-vous vivre avec une résolution de seulement 41 étapes? Ou 80 étapes, mais perdre la fonction "phase correcte"? Ou 321 étapes mais seulement sur les broches 9 et 10? 24 juin. 162016-06-24 09:06:52

  0

Je pense que la dernière option serait géniale alors j'utilise deux Ard. planches. Pouvez-vous m'aider avec cette partie? Je ne suis pas familier 24 juin. 162016-06-24 10:51:31

  0

En discutant avec Gerben, j'ai juste pensé à une quatrième possibilité: Vous pourriez ralentir l'horloge principale du système à 8 MHz et utiliser les trois temporisateurs. Vous auriez alors 4 canaux PWM à 25 kHz avec 161 étapes sur un seul Arduino Uno. Le coût serait de perdre les fonctions de synchronisation ('millis()', 'delay()' et co.), D'avoir à ajuster les vitesses de transmission en série, et d'avoir tout le programme exécuté moitié moins vite. Serait-ce une option intéressante? 24 juin. 162016-06-24 19:22:12

  0

@EdgarBonet Merci pour vos excellentes réponses détaillées. Dans mon code actuel, je peux contrôler 31kHz quatre broches pwm. En même temps je peux utiliser l'écran LCD (j'utilise ici delay() pour éviter les scintillements) et le débit en bauds est de 9600. Donc si j'utilise votre suggestion 8MHz, quelle baudrate dois-je utiliser? 25 juin. 162016-06-25 10:53:24

  0

Avec la CPU @ 8 MHz, si vous 'Serial.begin (19200)', le débit en bauds réel sera de 9600 bps. 'delay()' peut fonctionner, mais en unités de 39.0625 μs. 25 juin. 162016-06-25 11:11:43

  0

Le meilleur matériel expliquant PWM avec les minuteurs AVR que j'ai trouvé jusqu'à présent est la vidéo YouTube * "[8. Arduino Timers and Counters] (https://www.youtube.com/watch?v=faCVhp7gm-g) *" (1 h 00 m 08 s). 13 févr.. 182018-02-13 00:32:39

8

Je poste cette deuxième réponse depuis que j'ai réalisé qu'il est possible d'avoir 4 canaux PWM à 25 kHz avec 161 étapes sur un seul Arduino Uno. Ce implique changing the main clock frequency to 8 MHz, ce qui a des effets secondaires puisque le programme entier sera deux fois moins rapide. Il consiste également à reconfigurer les trois minuteries, ce qui signifie perdre les fonctions de synchronisation Arduino (millis(), micros(), delay() et delayMicroseconds()). Si ces compromis sont acceptables, voici comment il va :

void setup() 
{ 
    // Set the main system clock to 8 MHz. 
    noInterrupts(); 
    CLKPR = _BV(CLKPCE); // enable change of the clock prescaler 
    CLKPR = _BV(CLKPS0); // divide frequency by 2 
    interrupts(); 

    // Configure Timer 0 for phase correct PWM @ 25 kHz. 
    TCCR0A = 0;   // undo the configuration done by... 
    TCCR0B = 0;   // ...the Arduino core library 
    TCNT0 = 0;   // reset timer 
    TCCR0A = _BV(COM0B1) // non-inverted PWM on ch. B 
     | _BV(WGM00); // mode 5: ph. correct PWM, TOP = OCR0A 
    TCCR0B = _BV(WGM02) // ditto 
     | _BV(CS00); // prescaler = 1 
    OCR0A = 160;   // TOP = 160 

    // Same for Timer 1. 
    TCCR1A = 0; 
    TCCR1B = 0; 
    TCNT1 = 0; 
    TCCR1A = _BV(COM1A1) // non-inverted PWM on ch. A 
     | _BV(COM1B1) // same on ch. B 
     | _BV(WGM11); // mode 10: ph. correct PWM, TOP = ICR1 
    TCCR1B = _BV(WGM13) // ditto 
     | _BV(CS10); // prescaler = 1 
    ICR1 = 160; 

    // Same for Timer 2. 
    TCCR2A = 0; 
    TCCR2B = 0; 
    TCNT2 = 0; 
    TCCR2A = _BV(COM2B1) // non-inverted PWM on ch. B 
     | _BV(WGM20); // mode 5: ph. correct PWM, TOP = OCR2A 
    TCCR2B = _BV(WGM22) // ditto 
     | _BV(CS20); // prescaler = 1 
    OCR2A = 160; 
} 

void loop() 
{ 
    analogWrite(3, 1); // duty cycle = 1/160 
    analogWrite(5, 53); // ~ 1/3 
    analogWrite(9, 107); // ~ 2/3 
    analogWrite(10, 159); // 159/160 
} 

Contrairement au other answer, cela n'a pas besoin d'une version modifiée de analogWrite(): le standard fonctionnera très bien. Seuls les soins doivent être veiller à ce que:

  1. La valeur écrite doit être comprise entre 0 (ce qui signifie toujours faible) et 160 (toujours HIGH), y compris.
  2. Seules les broches 3, 5, 9 et 10 sont disponibles. Tenter de analogWrite() aux broches 6 ou 11 ne manquera pas seulement de délivrer une sortie PWM, il changera également la fréquence sur les broches 5 ou 3 respectivement.

7

Vous pouvez configurer la minuterie 1 pour passer à 25 kHz en mode correct PWM de phase, et utiliser ses deux sorties sur les broches 9 et 10 comme ceci:

// PWM output @ 25 kHz, only on pins 9 and 10. 
// Output value should be between 0 and 320, inclusive. 
void analogWrite25k(int pin, int value) 
{ 
    switch (pin) { 
     case 9: 
      OCR1A = value; 
      break; 
     case 10: 
      OCR1B = value; 
      break; 
     default: 
      // no other pin will work 
      break; 
    } 
} 

void setup() 
{ 
    // Configure Timer 1 for PWM @ 25 kHz. 
    TCCR1A = 0;   // undo the configuration done by... 
    TCCR1B = 0;   // ...the Arduino core library 
    TCNT1 = 0;   // reset timer 
    TCCR1A = _BV(COM1A1) // non-inverted PWM on ch. A 
      | _BV(COM1B1) // same on ch; B 
      | _BV(WGM11); // mode 10: ph. correct PWM, TOP = ICR1 
    TCCR1B = _BV(WGM13) // ditto 
      | _BV(CS10); // prescaler = 1 
    ICR1 = 320;   // TOP = 320 

    // Set the PWM pins as output. 
    pinMode(9, OUTPUT); 
    pinMode(10, OUTPUT); 
} 

void loop() 
{ 
    // Just an example: 
    analogWrite25k(9, 110); 
    analogWrite25k(10, 210); 
    for (;;) ; // infinite loop 
} 

écriture d'une valeur de 0 à analogWrite25k() signifie la broche sera toujours , alors que 320 signifie toujours HAUTE. Le analogWrite() devrait presque fonctionner, mais il interprétera 255 le même que 320 (c'est-à-dire toujours HAUTE).

Ce code suppose une carte Arduino Uno ou similaire (ATmega168 ou 328 @ MHz). La méthode utilisée ici nécessite un minuteur de 16 bits, et donc utilise Minuterie 1 car c'est la seule disponible sur l'Uno; C'est pourquoi seules deux sorties sont disponibles. La méthode pourrait être adaptée à d'autres cartes basées sur AVR avec un temporisateur de 16 bits. Comme Gerben l'a noté, ce temporisateur devrait avoir un registre ICRx correspondant. Il y a 4 minuteurs de ce type sur l'Arduino Mega , chacun avec 3 sorties.

+1

Il peut être utile d'expliquer que cette méthode ne fonctionne que pour timer1, car les autres temporisateurs n'ont pas de registre 'ICRx'. Tout au plus, vous ne pouvez avoir qu'une seule broche PWM par minuterie, pour les minuteurs 0 et 2. 24 juin. 162016-06-24 13:04:19

+1

@Gerben: Toutes les minuteries 16 bits ne possèdent-elles pas ce registre? Au moins sur le Mega ils le font. 24 juin. 162016-06-24 13:09:20

+1

Oui, mais seul timer1 est 16 bits sur l'ATMega328. Le reste est 8 bits. Et l'OP veut 4 sorties PWM, et votre solution ne fournit que 2. Ou je me trompe? 24 juin. 162016-06-24 15:12:53

+1

@Gerben: Non, vous avez raison. Je dis juste que le fait d'exiger ICRx semble être redondant avec exiger que le temporisateur soit 16 bits. Pour le Uno et Mega au moins, pas sûr d'autres Arduinos AVR. L'OP comprend que cela ne fournit que 2 canaux PWM: voir mon commentaire sur sa question et sa réponse. 24 juin. 162016-06-24 15:48:45

  0

Sur l'ATMega328 (que l'OP utilise) seul timer1 a le registre 'ICRx'. Pour les autres, vous devrez utiliser 'OCRxA' comme TOP, ce qui rendra impossible l'utilisation de PWM sur la broche' OCxA'. Le PO a dit qu'il/elle était d'accord avec seulement deux broches PWM, mais a ensuite dit qu'il/elle utiliserait deux Arduinos. Il devrait toujours être possible de faire avec seulement 1 Uno, si l'OP est prêt à perdre «millis» et «delay». 24 juin. 162016-06-24 16:16:08

  0

@Gerben: Un seul Uno? Parlez-vous des deux autres options que j'ai proposées (c'est-à-dire mettre les prescalers à 8)? Oh, on pourrait aussi changer la fréquence de l'horloge principale et avoir 161 pas, je n'avais pas à ce sujet. Est-ce ce que vous avez en tête? 24 juin. 162016-06-24 17:24:44

  0

Je ne suivais pas vraiment le fil de commentaires principal. Je parlais en effet de votre alternative 41 étapes. (Je ne suis pas sûr si l'OP a vraiment besoin de plus de 41 étapes pour le contrôle RPM.) 24 juin. 162016-06-24 18:36:07

  0

@Edgar Bonet J'essaye de suivre ceci et de générer le même 25khz sur la broche 8 de arduino mega qui est contrôlée par TIMER 4; Je ne vois aucun succès; S'il te plait peux-tu aider? 14 sept.. 172017-09-14 19:08:51

+1

@techniche: 1. Fonctionne pour moi. Peut-être avez-vous oublié de mettre 'COM4C1' dans' TCCR4A'? 2. Si ce n'est pas le problème, lisez [Comment poser une bonne question?] (Https://arduino.stackexchange.com/help/how-to-ask), puis mettez à jour [votre question] (https://arduino.stackexchange.com/questions/44750) en incluant votre code source complet et en indiquant clairement ce que vous attendez du programme et ce qu'il fait à la place ("Je ne vois aucun succès" n'est pas considéré comme un énoncé de problème valide). 15 sept.. 172017-09-15 08:43:10

  0

@EdgarBonet - merci beaucoup pour la réponse et l'aide; Je suis capable de générer le signal pwm et quelqu'un d'autre l'a vérifié avec un ventilateur de 64 gt alpin et cela semble fonctionner; ce ne fonctionne pas avec le ventilateur, j'ai https: //www.amazon.in/StorinTM-CPU-Cooler-Connecteur/dp/B06XJV1SH8/Il s'agit d'un ventilateur CPU standard avec 4 fils et son infact beaucoup utilisé; pourrait-il être un problème avec le ventilateur et le fil de pwm est juste pour montrer? 18 sept.. 172017-09-18 07:39:22