Por que alguns pinos têm uma frequência PWM diferente?

20

De acordo com a referênciaanalogWrite() do Arduino , a frequência PWM na maioria dos pinos é de ~ 490 Hz. No entanto, é ~ 980 Hz para os pinos 5 e 6 no Uno e para os pinos 3 e 11 no Leonardo.

Por que isso é diferente? É um recurso de design deliberado ou de alguma forma é ditado pelo hardware?

Peter Bloomfield
fonte

Respostas:

23

Essas não são as únicas frequências disponíveis para os sinais PWM. No entanto, são as frequências determinadas pelo pré-calibrador aplicado (que você pode alterar facilmente conforme detalhado abaixo).

Cada um dos 3 pares de pinos PWM está vinculado a um temporizador, cada um com sua própria frequência base, da seguinte maneira:

  • Os pinos 5 e 6 são emparelhados no timer0, com frequência base de 62500Hz
  • Os pinos 9 e 10 são emparelhados no timer1, com frequência base de 31250Hz
  • Os pinos 3 e 11 são emparelhados no timer2, com frequência base de 31250Hz

Então, cada conjunto de pinos possui vários valores pré-calibradores que podem ser escolhidos, que dividirão a frequência base desse par de pinos. Os valores disponíveis do pré-calibrador são:

  • Os pinos 5 e 6 têm valores pré-calibradores de 1, 8, 64, 256 e 1024
  • Os pinos 9 e 10 têm valores pré-calibradores de 1, 8, 64, 256 e 1024
  • Os pinos 3 e 11 têm valores pré-calibradores de 1, 8, 32, 64, 128, 256 e 1024

As diferentes combinações produzem diferentes frequências em um dado pino PWM. Observe que o timer 2 (vinculado aos pinos 3 e 11) tem mais valores pré-calibradores disponíveis, resultando em mais frequências disponíveis.

Agora, por que o timer 2 é diferente, essa é uma pergunta separada.

Edit: Aqui está uma lista de possíveis frequências PWM por pino ( deste artigo ):

Para os pinos 6 e 5 (OC0A e OC0B):

  • Se TCCR0B = xxxxx001, a frequência é de 64 kHz
  • Se TCCR0B = xxxxx010, a frequência é 8 kHz
  • Se TCCR0B = xxxxx011, a frequência é 1kHz (esse é o padrão do gerenciador de inicialização Diecimila)
  • Se TCCR0B = xxxxx100, a frequência é 250Hz
  • Se TCCR0B = xxxxx101, a frequência é 62,5 Hz

Para os pinos 9, 10, 11 e 3 (OC1A, OC1B, OC2A, OC2B):

  • Se TCCRnB = xxxxx001, a frequência é 32kHz
  • Se TCCRnB = xxxxx010, a frequência é de 4 kHz
  • Se TCCRnB = xxxxx011, a frequência é 500Hz (esse é o padrão do carregador de inicialização Diecimila)
  • Se TCCRnB = xxxxx100, a frequência é 125Hz
  • Se TCCRnB = xxxxx101, a frequência é 31,25 Hz

TCCRnBÉ onde você define os bits do pré-calibrador para o timer n, substituindo npor 0, 1 ou 2, dependendo do timer que deseja definir. Se você ainda não tiver certeza sobre as operações bit a bit, leia este tutorial de matemática em bits .

Minhas fontes:

Observe que parece haver divergência nessas fontes sobre se os pinos 9 e 10 têm o mesmo comportamento que 5 e 6 ou 3 e 11, mas você entendeu a ideia de qualquer maneira. Estou lendo o datashet para tentar descobrir o que é correto ou se isso é uma diferença entre as placas.

Ricardo
fonte
11
A que ATmega esta resposta se refere? Não fiz check, mas aposto que difere um pouco por controlador.
jippie
@jippie Bom ponto! As fontes referem a ATmega168 e 328.
Ricardo
@jippie Apenas para esclarecer, na minha resposta, os números dos pinos referem-se à forma como são atribuídos na placa Uno (o pino 1 significa o pino digital 1 ou D1, por exemplo), não o IC (o pino 1 do ATmega328 é redefinido).
Ricardo
11
Eu acredito que esses detalhes mudar também com placas, Uno, Duemilanove, mega, ...
jippie
Definitivamente, sim.
Ricardo
8

Não conheço as considerações de design, mas se você verificar a folha de dados do microcontrolador no seu Arduino, notará que os pinos PWM estão agrupados e por grupo conectado a um timer. A velocidade na qual esse timer é aumentado varia de acordo com o pré-calibrador configurado. Se você alterar o pré-calibrador para um determinado temporizador, alterará a frequência PWM para os pinos PWM relacionados. Acredito que alguns temporizadores duplicam para outros fins, como a millis();função. Se você alterar o pré-calibrador para esse timer, os valores retornados por millis()serão desativados pelo mesmo fator.

Você pode calcular a configuração do pré-calibrador da seguinte maneira:

$$ \ text {prescaler} = \ dfrac {f_ {CPU}} {PWMresolution × f_ {PWM}} = \ dfrac {16 \ text {MHz}} {256 × 490} \ aproximadamente 128 $$

prescaler = f [CPU] / (resolução PWM × f [PWM]) = 16000000 / (256 × 490) = aproximadamente 128.

Verifique a folha de dados e você verá que 128 é realmente um dos valores do pré-calibrador que você pode selecionar.

jippie
fonte
2
Rapaz, sentimos falta do MathJax ou o quê? Espero que possamos ativá-lo após a versão beta.
Ricardo
11
@ Ricardo Eu tenho um botão MathJax no meu navegador; o) meta.arduino.stackexchange.com/questions/13/…
jippie