Estaba trabajando en mi cañon de Gauss, y necesitaba generar pulsos aislados de una duración determinada. Hay varias formas, pero me interesa una que me permitiese generar los pulsos de una duración muy precisa. Así qué vamos a intentar usar los temporizadores del propio ATmega para que los tiempos sean más precisos.

Temporizadores del ATmega

Para hacer este experimento, vamos a usar el Arduino Nano con el ATmega168. Nosotros vamos a usar el TC2, un temporizador de 8 bits, que puede funcionar en los siguientes modos:

Tabla de modos de contadores.

Tabla de modos de contadores.

En nuestro caso vamos a usar el modo Fast PWM.  Los temporizadores tienen asignadas unas salidas (OC2A y OC2B), que se puede elegir cuando se pone a valor alto y cuando a valor bajo. Para elegir cómo se comportan las salidas se pueden modificar los valores de COM2B1 y COM2B0 según la siguiente tabla.

Modos de "Compare Output"

Modos de “Compare Output”

Tanto el modo de funcionamiento (para elegir el Fast PWM) y el funcionamiento de OC2x se configuran en el registro TCCR2A. El funcionamiento del Fast PWM se puede resumir en:

  • El contador aumenta hasta el valor de OCRA, en ese momento se pone a 0.
  • Cuando el contador vale 0, el pin de salida se pondría a bajo.
  • El pin OC2B cambiará a valor alto cuando el contador valga OCRB.

Usando las reglas podemos ver un par de cosas:

  • Si OCRA vale 1, el contador se quedará atascado entre 0 y 1 y nunca llegará al máximo (0xFF)
  • Si ponemos el valor de OCRB en el máximo menos 1, el pin OC2B estará en alto un ciclo ya que cuando llegue al máximo se reiniciará.

Hackeando el TC2

Con todo lo anterior podemos hacer una cosa:

  • Dejamos el contador atascado con el OCRA en 1 o en 0. De esta manera nunca llegará al valor de OCRB.
  • Cuando queramos que empiece el pulso ponemos el contador muy cerca del OCRB.
  • La duración del pulso la podemos controlar con la distancia entre el OCRB y el máximo.

Podemos ver un esquema de este funcionamiento en la siguiente imagen:

Funcionamiento del contador

Funcionamiento del contador

La duración del pulso dependerá de la frecuencia y el número de ciclos a contar. Por ejemplo, en el caso del Arduino Nano que estoy usando, que funciona a 16 Mhz, cada ciclo serán 62.5 nano segundos.

Además podremos configurar el preescaler para hacer pulsos de duración más larga. Para ellos habría que configurar el TCCR2B, los bits C22, C21 y CS20.

Código con Arduino

Cómo ya expliqué, yo uso platformIO para desarrollar de manera más cómoda. Así que veréis que hay un #include <Arduino.h> que los que usen el IDE de Arduino no necesitan.

Setup

Lo primero que necesitamos es hacer el Setup para configurar el contador. Vamos a suponer que queremos generar un pulso de 500 ns, que son aproximadamente 8 ciclos de reloj.

void setup(){

  // Desactivamos el reloj del contador.
  TCCR2B = 0;

  // Hacemos que el contador se quede atascado.
  OCR2A = 0;

  // Ponemos el OCR2B para que haga 8 ciclos
  // Restamos uno porque entre el 0xFF y el 0x00 pasa otro ciclo
  OCR2B = 0xFF-(8-1);

  // Configuramos el Compare Output y el Modo de PWM
  // Acorde a las tablas del datasheet
  TCCR2A = _BV(COM2B0) | _BV(COM2B1) | _BV(WGM20) | _BV(WGM21);
  TCCR2B = _BV(WGM22)| _BV(CS20);

  // Activamos el Pin D3 de Arduino
  pinMode(3, OUTPUT);
}

Todo junto: código final

La parte del loop es muy sencilla, vamos a lanzar el pulso, una vez cada segundo y para ello forzamos el contador (TCNT2) al valor del OCR2B-1. Así que ponemos ya el código final

#Este include solo si trabajas con platformIO
#include <Arduino.h>

void setup(){

    // Desactivamos el reloj del contador.
    TCCR2B = 0;

    // Hacemos que el contador se quede atascado.
    OCR2A = 0;

    // Ponemos el OCR2B para que haga 8 ciclos
    // Restamos uno porque entre el 0xFF y el 0x00 pasa otro ciclo
    OCR2B = 0xFF-(8-1);

    // Configuramos el Compare Output y el Modo de PWM
    // Acorde a las tablas del datasheet
    TCCR2A = _BV(COM2B0) | _BV(COM2B1) | _BV(WGM20) | _BV(WGM21);
    TCCR2B = _BV(WGM22)| _BV(CS20);

    // Activamos el Pin D3 de Arduino
    pinMode(3, OUTPUT);
}

void loop(){

    // Ponemos el contador justo antes del OCR2B
    TCNT2 = OCR2B - 1;


    delay(1000);
}

Resultados

A continuación os dejo los resultados medidos con el osciloscopio para varias duraciones de pulso. Espero que os haya parecido útil y halláis aprendido algo más de los ATmega 🙂

Captura del pulso de 63ns

Captura del pulso de 63ns

Captura del pulso de 501 nanosegundos

Captura del pulso de 501 nanosegundos

Captura del pulso de 1.5 microsegundos

Captura del pulso de 1.5 microsegundos

Categorías: Arduino

Gluón

Teleco con ganas de aprender más y compartirlo. Viajero empedernido y amante de la fotografía y la tecnología. Espero dejar mi granito de arena y que este pueda servir de ayuda.

0 commentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *