lunes, 2 de mayo de 2011

Uso de PWM en ATMEGA16

En la publicación del día de hoy mostraré un ejemplo práctico con código fuente incluido para el uso del módulo PWM del microcontrolador ATMEGA16. Este ejemplo se hace para este microcontrolador en específico, pero es posible aplicarlo a cualquier otro microcontrolador ATMEGA que tenga módulo PWM cambiando los correspondientes registros.

Se debe controlar un motor DC usando una señal PWM (generada con el Timer 0 en modo PWM con corrección de fase), la cual puede tener 8 niveles de ciclo de trabajo, desde 0% hasta 100%. Los niveles del PWM se deben modificar a través de dos interruptores pulsadores con los que se podrá incrementar o reducir un nivel de ciclo de trabajo por cada pulsación de éstos. Adicionalmente, el nivel actual del PWM se debe mostrar usando una barra de LEDs conectada al puerto C del microcontrolador.

El código fuente para solucionar el anterior ejemplo, se muestra a continuación:


//*****************************************************
// Programa para el control de velocidad de un motor DC
//
// Descripción: Mediante este programa se usa el módulo
// de PWM con corrección de fase del Timer 0 para el
// control de la velocidad de un motor DC a través de
// dos pulsadores, los cuales permiten aumentar o
// reducir la velocidad

//*****************************************************

// Dispositivo = ATMEGA16
// Fclk = 1.0MHz

#include<avr/io.h>


int main(void)
{

// Variable que guarda el nivel de velocidad
// del motor (0..8)
volatile char nivel=0;

// Configuración de dirección de puertos I/O
DDRA=0x00; // Puerto A como entrada
DDRC=0xFF; // Puerto C como salida
DDRB|=(1<<DDB3);// Pin 3 de puerto B como salida

PORTA=0xFF; // Habilitación de pull-ups del puerto A
PORTC=0x00; // Inicialización de salida del puerto C

// Configuración del Timer 0:
// * Modo PWM con corrección de fase
// * Modo no inversor
// * Fuente de reloj directa desde el oscilador del microcontrolador
TCCR0|=(1<<WGM00)|(1<<COM01)|(1<<CS00);

// Inicialización del PWM
OCR0=0x00;

// Ciclo de polling
while(1)
{
// Se evalúa si se ha presionado algún botón
if(PINA!=0xFF)
{
// Se evalúa cual botón se presionó
switch(PINA & 0x03){
case 1: if(nivel<8)
nivel++; // Incrementa velocidad
break;
case 2: if(nivel>0)
nivel--; // Decrementa velocidad
break;
};

PORTC=(1<<nivel)-1; // Visualización en barra de LEDS

OCR0=32*nivel-1*(nivel!=0); // Actualización de PWM

// Ciclo que pone el sistema en espera hasta que
// se libere el botón presionado
while(PINA!=0xFF)
{
asm("nop");
}
}
}

}

Para solucionar el anterior ejemplo, se observa que se inicializan los puertos asignando su correspondiente dirección, y posteriormente se inicia la unidad Timer0 en el modo PWM con corrección de fase. Luego, en el ciclo de polling se evalúa constantemente si se ha presionado alguno de los botones, y cuando esto es cierto, se procede a incrementar el nivel del PWM, se visualiza a través de la barra de LEDs y se actualiza el registro OCR0, con el cual se controla el ancho de pulso generado. Finalmente se introduce un ciclo de espera, en el cual se detiene el ciclo principal hasta que se suelte el botón que ha sido presionado. A continuación se muestra el diagrama esquemático para esta aplicación:


Link recomendado: http://www.administracionsatelital.com/

1 comentario:

  1. Amigo buenas tardes. Actualmente estoy necesitando hacer un pwm a una frecuencia de 60Hz. Pero solo necesito generar en un periodo el pwm de 0% a 100%. Mejor dicho como un ciclo de reloj. El problema que tengo es que no se configurar en avr studio el micro para que por el puerto B3 me mando esta señal.

    Si puede colaborarme le agradecería mucho.

    ResponderEliminar