Hardware e Timers do Arduino

Para mais informações e aprofundamento (e também como parte da referência bibliográfica) aqui se encontra o datasheet do hardware do Arduino. Este arquivo, apesar de ser bem técnico e complexo, é bem completo e aprofundado. Então, realmente é uma grande ajuda para quem quer mergulhar no mundo do Arduino e da eletrônica.


Nesta página iremos aprofundar mais o funcionamento e os conceitos acerca do Timer 1 que o Arduino possui.

Introduzindo o conceito de clock

Um clock é uma onda periódica quadrada que alterna por um certo momento em um nível lógico alto (também chamado de nível lógico '1', high) e em outro momento em um nível lógico baixo (nível '0', low). Além disso, o tempo que a onda permanece em '1' ou em '0' pode ser programado, que está relacionado com o duty cycle. Por exemplo, em todo o período da onda, se o nível '1' permanece durante 3/4 do período da onda, então '0' permancerá por 1/4, assim esta onda tem um duty cycle de 75%.

Com essas informações iniciais, podemos prosseguir.

Funcionamento do Timer 1 do Arduino UNO

Dentre alguns timers e seus respectivos modos de operação que o Arduino UNO (e também o NANO) possui, apenas um dos modos e um dos timers será utilizado. O modo a ser utilizado será o CTC (Clear Timer on Compare Match) no Timer 1. Para configurar o timer a esse modo, o registrador WGM1 (Wave Generation Mode) é utilizado. Para melhor entendermos o funcionamento do timer, um Compare Match é um fenômeno que acontece dentro das configurações de um contador que faz o timer reiniciar. É como se um marcador fosse colocado na contagem, e quando o contador atinge esse marcador, acontece um Compare Match e, em seguida, o timer reinicia.

Por exemplo, internamente, o Arduino possui um clock de 16 MHz interno e um registrador de 16 bits no Timer 1, chamado de TNCT1 (Timer Counter Value Register, em que "1" se refere ao número do timer), como mostra a Figura 1. Assim, ele funciona como um contador de 400 passos, que conta de um em um, do 0 até o 399. Ao atingir 399 (o topo), acontece um Compare Match e o contador retorna ao 0 novamente. Assim, a frequência da ocorrência de cada um dos 399 passos é a de 16 MHz.

Figura 1: Gráficos que representam o funcionamento dos timers

No modo CTC, há um outro registador chamado OCR1A (Output Compare TC1A Register, em que TC é a sigla para Timer Counter) que recebe um valor inteiro definido durante a programação do timer do Arduino, entre 0 e 255. Caso OCR1A=199, haverá um Compare Match no passo 199, reiniciando o timer neste passo. Assim, o valor do OCR1A, dita o valor da frequência do sinal quadrado que irá ser fornecido pelos terminais do Arduino, como será mais explicado a frente.

Há outros registradores COM1A e COM1B (Output Compare Mode, em que "A" e "B" se referem a unidade dos canais do Output Compare) que fazem a comunicação entre o TCNT1 e os pinos digitais de saída do Arduino. As saídas digitais do Timer 1 são os pinos 9 e 10, chamados respectivamente de OC1A e OC1B (Output Compare). A saída desse Timer 1 é pré-definida e inalterável para que o nível lógico do sinal do OC1A seja sempre o oposto do nível lógico do sinal do OC1B. Isso é muito importante para o funcionamento dos emissores ultrassônicos do levitador, já que a onda sonora é gerada a partir de uma inversão intermitente da polaridade do sinal nos terminais do emissor. Na programação a ser discutida mais a frente, configuramos a comunicação entre o TCNT1 e as saídas digitais, pelos registradores COM1A e COM1B para que quando houver um Compare Match, as saídas OC sofram um toggle, isto é, inverte o nível lógico que estava no OC1A e no OC1B antes de haver o Compare Match, como mostra a Figura 1.


Existe também outro registrador que é o CS1 (Clock Select) que habilita o timer para funcionar e seleciona por quanto a frequência do TCNT1 será divido, esse divisor é chamado de prescaler. No caso desta configuração, apenas habilitaremos o funcionamento do timer sem nenhuma diminuição do período, pois uma mudança no prescaler pode prejudicar o bom funcionamento do timer.

Novamente sobre o código de programação

Tendo em vista os registradores já discutidos, existem mais alguns a serem considerados.  Como o FOC1A e FOC1B (Force Output Compare) que força respectivamente uma atualização do estado das saída OC1A e OC1B como se tivesse acontecido um Compare Match, porém sem ter realmente acontecido e sem ter reiniciado o timer. Isso é extremamente importante, pois esse recurso será utilizado para manter o estado lógico da saída OC1B como o oposto do estado lógico da saída OC1A.  Há também o registrador  GTCCR (General Timer/Counter) que é responsável por pausar e reiniciar os  timers. Essa pausa nos timers garante que a atualização do OCR1A não seja feita depois de ter passado do seu valor, evitando uma dessincronização dos sinais elétrico

Além disso,  existem os registradores mais importantes de toda a programação: TCCR1A, TCCR1B, TCCR1C (Timer/Counter Control Register).  Esses três registradores juntos contém todos os outros registradores já mencionados (WGM, COM, CS e FOC) e por isso fazem o controle deles. É por esses três grandes registradores de 8 bits, que os valores de WGM, COM, CS, FOC são selecionados e assim o timer é configurado para funcionar como queremos aplicá-lo. Isso pode ser visto no código de programação, em que a função configuraTimers() é criada.

Para mais informações e, como parte da referência bibliográfica, aqui se encontra o datasheet do hardware do Arduino