INSTITUTO POLITÉCNICO NACIONAL UNIDAD PROFESIONAL INTERDISCIPLINARIA EN INGENIERÍA Y TECNOLOGÍAS AVANZADAS
MICROCONTROLADORES AVANZADOS Práctica 3 – Generación de un PWM
Alumnos
Cadena Díaz Daniel Alberto Calleja Tamez Moises Sánchez Cortés Luis Gerardo
Profesor: Méndez Martínez Mauricio
Grupo: 4MM5
Introducción Un PWM (Pulse-Width Modulation) es una técnica en la que se modifica el c iclo de trabajo de una señal periódica, ya sea una señal senoidal o cuadrada, por ejemplo, para transmitir información a través de un canal de comunicaciones o controlar la cantidad de energía que se envía a una carga. En este caso entendemos como el ciclo de trabajo al ancho de su tiempo en alto en relación con el periodo de la misma. “
”
Dentro de las aplicaciones del mismo, se puede utilizar para controlar fuentes conmutadas, controles de motores, controles de elementos termoeléctr icos, choppers para sensores en ambientes ruidosos entre otros. Un servomotor, también comúnmente denominado como servo, es un dispositivo bastante similar a un motor de corriente continua, que tiene la capacidad de colocarse en cualquier posición dentro de su rango de operación, y mantenerse estable en dicha posición. Puede ser controlado tanto en velocidad, como en posición.
Objetivos Utilizando el ATMega16 realizar un programa que sea capaz de controlar un servomotor para posicionarlo desde 0° hasta 180° en lapsos de 45°, es decir, 0° - 45° - 90° - 135° - 180°. Para esto se requerirá generar primero una señal cuadrada utilizando el Timer0 o el Timer1 y después de esto, modificar el tiempo en alto en el que deba estar esta señal, dependiendo del servo que utilicemos, pues dependiendo de éste, varían los tiempos en los que se debe de encontrar en alto para controlar las posiciones.
Desarrollo El código realizado para la práctica es e l siguiente: // Programa que controlará un motor PWM utilizando el Timer0 // Se declara la frecuencia del procesador #define F_CPU 8000000UL // Declaración de librerías #include
#include // Librería para interruptions #include
// Librería donde se encuentra _NOP();
// Global variable volatile uint8_t conTmr0, conTmr1;
// Function initializing the value of Timer0 prescaling and the number // which is starting at. void timer0_init() { // Disabling any kind of interrupts cli();
// ------------------- TIMER 0 ---------------------- // Cuenta 0.01 ms
// TIMER0 prescaling. (010 -> F_CPU /8 TCCR0 |= (0 << CS10) | (1 << CS01) | (0 << CS00); // Initialization of the counter TCNT0 = 157;
// ------------------- TIMER 1 ---------------------- // Cuenta 5s // TIMER1 preescaling (101 -> F_CPU / 1024) TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10); // TIMER1 initialization TCNT1=0x676A;
// Enabling the overflow interrupt in TMR0 and TMR1 TIMSK |= (1 << TOIE1) | (1 << TOIE0);
// Initializing overflow counter variable conTmr1 = 0; conTmr0 = 0; // Enabling global interrupts sei(); }
// Interrupt Service Routine (ISR) ISR(TIMER0_OVF_vect) // What should the program do when the TMR0 overflows // i.e every 0.1ms. {
conTmr0++; if (conTmr1 == 0) // Para 1 ms o, 0° { if (conTmr0 <= 5) { PORTA = 1; }
else { PORTA = 0;
if (conTmr0 >= 200) { conTmr0 = 0; } } } if (conTmr1 == 1) // Para 1 ms o, 0° { if (conTmr0 <= 10) { PORTA = 1; } else { PORTA = 0;
if (conTmr0 >= 200) { conTmr0 = 0; } } } if (conTmr1 == 2) // Para 1 ms o, 0° { if (conTmr0 <= 15) { PORTA = 1; } else {
PORTA = 0;
if (conTmr0 >= 200) { conTmr0 = 0; } } } if (conTmr1 == 3) // Para 1 ms o, 0° { if (conTmr0 <= 20) { PORTA = 1; } else { PORTA = 0;
if (conTmr0 >= 200) { conTmr0 = 0; } } } if (conTmr1 == 4) // Para 1 ms o, 0° { if (conTmr0 <= 24) { PORTA = 1; } else { PORTA = 0;
if (conTmr0 >= 200) { conTmr0 = 0; } } }
TCNT0 = 157; }
ISR(TIMER1_OVF_vect) // What should the program do when TMR1 overflows // i.e every 5 seconds. {
// HIGH TCNT1 = 0x676A; conTmr1++; if (conTmr1 > 4) conTmr1 = 0; }
// Main program int main(void) { // PINA0 is declared as an output DDRA |= (1 << 0);
// Calling the function timer0_init() who has the values of TMR0. timer0_init();
while(1) { _NOP(); }
}
La clave para poder realizar esta práctica consiste en tomar lapsos de 0.1 milisegundos en el TIMER0, haciendo una interrupción con desborde. Como el servomotor que utilizamos se posiciona en 0° en 0.5ms, en 90° en 1.5ms y 180° en 2.5ms, lo que se hace es en un periodo de 20ms, o 200 conteos de desborde, poner durante 5 desbordes en alto la salida del PINA0 y el resto del conteo en bajo, y con una regla de 3, podemos determinar cuántos conteos serán utilizados tanto para 45° y 135°. Con el TIMER1 se definió un tiempo de 5 segundos, y durante este tiempo, se mantendrán cada una de las 5 posiciones anteriormente mencionadas.
Conclusiones La utilidad que nos brinda un PWM es de gran cantidad y se pueden ocupar en muchos ámbitos a lo largo de nuestra carrera, desde el control de un pequeño servo, hasta aplicaciones de integración mucho más com plejas. Además nos ayuda a practicar el uso de los Timers no sólo como una herramienta de conteo, sino también como una herramienta de control para nuestras aplicaciones.