TUTORIAL TACOMETRO EN LCD CON ATMEGA8 Por Óscar Razo Navarrete INSTITUTO TECNOLÓGICO DE ESTUDIOS SUPERIORES DE ZAMORA DPTO. DE INGENIERIA ELECTRÓNICA.
Este es el primer tutorial que realizo para COMUNIDAD ATMEL, ATMEL, y espero seguir aportando conocimientos. Básicamente se trata de un tacómetro que valga la redundancia, nos servirá para medir m edir las vueltas que da la flecha de un pequeño motor de 5 volts durante un minuto, el valor de las RPM será desplegado en una pantalla de LCD de 16x2, aunque también se pueden desplegar los datos en displays si así lo quisiéramos, pero yo escogí la pantalla porque es mas fácil, se ahorran pines, y puse un texto en la línea de debajo de la pantalla el cual dice: ’’COMUNIDAD ATMEL’’.
FUNCIONAMIENTO
La forma que determina el funcionamiento de este programa es sencillo. Utilizaremos el Timer0 del ATMEGA8, el cual tiene una función que nos permite contar los pulsos externos generados por un motor que tiene un disco (hecho con un pedazo de cartón) con 8 agujeros, el cual esta en medio de un emisor y un receptor infrarrojos, y es el receptor el que el que enviará los pulsos a el pin numero6 (que corresponde al bit 4 del puerto D) cada vez q el rayo es interrumpido. Una vez que son los 100ms se lee el valor que existe en el TMR0, lo multiplica por 75 esto debido al tiempo por minuto y el producto entre los agujeros 8, nos da como resultado 75.(O sea como estamos muestreando cada 100ms, entonces en un segundo caben 10 veces 100 ms de acuerdo? Esto quiere decir que a un minuto le caben 600 veces 100ms (espero haberme explicado) y es por esto que 600/8=75 (8 es el numero de agujeros). Por lo tanto el numero menor de revoluciones que podremos medir serán 75, ya que el numero menor de pulsos que se pueden medir en 100ms es 1 y entonces 1x75=75.
Diferentes vistas del motor DC de 5 volts con un disco hecho de cartón el cual tiene 8 agujeros.
NOTA: Si se desea obtener una mayor resolución, será necesario hacer mas agujeros en el disco,
por ejemplo si el disco tiene 60 agujeros, entonces haremos: 600/60=10 y para este caso el numero menor que se puede medir será de 10 RPM, pero para efectos de este tutorial se utilizará el disco con 8 perforaciones.
Emisor y receptor infrarrojos.
aquí estará el disco girando para interrumpir el rayo infrarrojo y contar los pulsos
Diagrama esquematico
De aquí tomaremos laseñal para conectar Al bit 4 del puerto D, o lo que es lo mismo el pin numero 6 del ATMEGA8.
Como se dijo anteriormente, los pulsos se cuentan de tal manera que en un lapso de 100ms capturamos el numero de pulsos que se generaron en el pin(es decir estamos haciendo un muestreo del contador del timer0 cada 100ms) y luego este valor(TCNT0), se multiplica por 75 para obtener el resultado, posteriormente este resultado se compara con el numero 9999 (esto debido a que solamente utilizé 4 digitos y el valor máximo que se puede desplegar en 4 digitos es 9999) y si es menor a 9999, se divide entre 1000 para obtener el numero de los millares, el residuo se divide entre 100 para obtener las centenas, el residuo de las centenas se divide entre 10 para obtener las decenas, y el residuo de las decenas simplemente lo colocamos en las unidades. IMPORTANTE: Es necesario estar refrescando el TCNT0, para que cada muestreo nos de el numero
de pulsos correspondiente, y por eso al principio de la ejecución del programa borramos el TCNT0 (ya que si no lo borramos, el valor del TCNT0 se acumularía para el siguiente muestreo y nos daría una lectura errónea del valor real de los pulsos obtenidos en ese siguiente muestreo)
CODE WIZARD
Haremos un nuevo proyecto en el code wizard en el cual escogeremos el ATMEGA8 (ojo no es el ATMEGA 48, aunque también es posible realizar el programa, pero los timers son un poco distintos asi que debemos tener cuidado a la hora de seleccionar nuestro microcontrolador, y checar su respectiva hoja de datos) con una frecuencia interna de 1 MHZ, es importante señalar que el code wizard no nos da la opción de dividir la frecuencia para el atmega8, como en el atmega48, solo escogeremos 1MHZ y listo. Tambien seleccionaremos la pantalla de 16X2 para ser utilizada en el puerto B. En la pestaña de ‘’timers’’ vamos a dar click en ‘’Timer0’’ y luego e n ‘’clock source’’ vamos a
seleccionar la opción de ‘’T0 pin Falling Edge’’ porque los pulsos se contarán cuando haya un ‘’0’’ lógico. En la pestaña de ‘’ports’’ vamos a seleccionar el ‘’pull up’’ del bit 4 del puerto D, ya que es por este
pin por donde vamos a contar los pulsos, y si no le ponemos el ‘’pull up’’ podrían filtrarse señales no deseadas por este pin.
Aquí seleccionamos ATMEGA8 a 1MHZ
Seleccionar pantalla LCD en el puerto B
Aquí seleccionamos el timer0 en la opción ‘’T0 pin F alling Edge’’
Y por ultimo habilitar ‘’pull up’’ del bit 4 del puerto D
El siguiente es el código generado por el code wizard y lo que está en color azul es lo que se debe agregar al programa: /***************************************************** This program was produced by the CodeWizardAVR V2.03.6 Evaluation Automatic Program Generator © Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com
Project : Version : Date : 12/05/2009 Author : Freeware, for evaluation and non-commercial use only Company : Comments:
Chip type
: ATmega8
Program type
: Application
Clock frequency
: 1.000000 MHz
Memory model
: Small
External RAM size : 0 Data Stack size
: 256
*****************************************************/
#include #include unsigned int x; // definimos x del tipo int porque el resultado de unsigned char y; // la multiplicacion no cabe en un byte const char z=0x4b; char unidades=0; char decenas=0; char centenas=0; char millares=0; char a=0; char b=0; char c=0; char d=0;
// Alphanumeric LCD Module functions #asm .equ __lcd_port=0x18 ;PORTB #endasm #include
// Declare your global variables here
void main(void) { // Declare your local variables here
// Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00;
// Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00;
// Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=P State3=T State2=T State1=T State0=T PORTD=0x10; DDRD=0x00;
// Timer/Counter 0 initialization // Clock source: T0 pin Falling Edge TCCR0=0x06; TCNT0=0x00;
// Timer/Counter 1 initialization // Clock source: System Clock
// Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected
ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00;
// External Interrupt(s) initialization // INT0: Off // INT1: Off MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;
// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00;
// LCD module initialization lcd_init(16);
lcd_gotoxy(1,1); lcd_putsf("COMUNIDAD ATMEL"); lcd_gotoxy(4,0); lcd_putsf("RPM=");
while (1) { // Place your code here
TCNT0=0;
//borramos el contador del timer 0
delay_ms(100); //Se hace un retardo de 100 milisegundos y=TCNT0; //pasamos el valor de TCNT0 a ‘’y’’ x=y*z; //recordemos que ‘’z’’ vale 75 if(x<=9999) //haremos las operaciones solamente si las RPM son menores de 9999 { millares=x/1000; x=x%1000; //aqui separamos el centenas=x/100; x=x%100; //valor de ‘’x’’ en unidades,decenas decenas=x/10; unidades=x%10; //centenas y millares }
a=0x30+millares; //le sumamos 0x30 b=0x30+centenas; //para desplegar los números c=0x30+decenas; //tal y como se vio en el d=0x30+unidades; //tutorial de LCD
lcd_gotoxy(8,0); //desplegamos lcd_putchar(a); //millares
lcd_gotoxy(9,0); //desplegamos lcd_putchar(b); //centenas
lcd_gotoxy(10,0); //desplegamos lcd_putchar(c); //decenas
lcd_gotoxy(11,0); //desplegamos lcd_putchar(d); //unidades
}; }
Este es el diagrama de conexión, cabe señalar que para efectos de simulación, se introdujo una señal de reloj en el pin T0.
Esta es una foto real del circuito ya funcionando.
Si se desea variar la velocidad del motor, simplemente con variar el voltaje de alimentación del motor es suficiente.
Bueno, en este tutorial trato de explicar lo mas que puedo, ojalá me haya dado a entender pero espero que lo entiendan para que armen el circuito, ya que funciona muy bien. Gracias.
Óscar Razo Navarrete, alumno del Instituto Tecnológico de Estudios Superiores de Zamora, en la carrera de Ingeniería en Electrónica.
mayo de 2009