Reporte - Villegas990/LabMicros_2Prac GitHub Wiki

Contador con velocidad variable



Descripción El estudiante implementará un sistema basado en microcontrolador. Dicho sistema irá incrementado un contador cada cierto tiempo. Dicho tiempo podrá ser modificado por el usuario mediante el uso de 2 push-buttons, uno para aumentar la velocidad y otro para disminuirla. El contador deberá ser mostrado en un display de 7 segmentos e indicar mediante 5 leds la velocidad seleccionada. Objetivo Familiarizarse con el uso y programación de ‘delays” para generar retrasos en la ejecución de algún sistema. Material

       Protoboard
       PIC18F4550
       2 push buttom
       Display de 7 segmentos
       Resistencia de 1KΩ
       5 leds

Desarrollo La primera parte que desarrollamos fue el contador de 9-0, donde nuestro numero esta guardado en la variable TEMP. En cuyo caso que nuestro numero ya sea 0, este se ira a la subrutina TURN_NINE donde tomara el valor de 10; teniendo TEMP un valor diferente a 0 este se restara para que sea decodificado y una vez decodificado ser mandara a nuestro display los números del 9 al 0.

       BASE:
              			MOVF	TEMP,W			;
              			BZ	TURN_NINE 		;
              			DECF	TEMP			;
              			CALL	DECODE			;
       DECODE:
              			MOVLW	0x00			;
              			SUBWF	TEMP,0			;
              			BZ	D_ZERO			;
              			MOVLW	0x01			;
              			SUBWF	TEMP,0			;
              			BZ	D_ONE			;
              			MOVLW	0x02			;
              			SUBWF	TEMP,0		        ;
              			BZ	D_TWO			;
              			MOVLW	0x03			;
              			SUBWF	TEMP,0			;
              			BZ	D_THREE			;
              			MOVLW	0x04			;              
              			SUBWF	TEMP,0			;
              			BZ	D_FOUR			;
              			MOVLW	0x05			;
              			SUBWF	TEMP,0			;
              			BZ	D_FIVE			;
              			MOVLW	0x06			;
              			SUBWF	TEMP,0			;
              			BZ	D_SIX			;
              			MOVLW	0x07			;
              			SUBWF	TEMP,0			;
              			BZ	D_SEVEN			;
              			MOVLW	0x08			;
              			SUBWF	TEMP,0			;
              			BZ	D_EIGHT			;.
              			MOVLW	0x09			;
              			SUBWF	TEMP,0			;
              			BZ	D_NINE			;	
              			RETURN;
       D_ZERO:
              			MOVLW	b'01111110'		;//0
              			MOVWF	PORTD			;
              			RETURN;
       D_ONE:
              			MOVLW	b'00110000'		;//1
              			MOVWF	PORTD			;
              			RETURN			;
       D_TWO:
              			MOVLW	b'01101101'		;//2
              			MOVWF	PORTD			;
              			RETURN		;
       D_THREE:
              			MOVLW	b'01111001'		;//3
              			MOVWF	PORTD			;
              			RETURN			;
       D_FOUR:
              			MOVLW	b'00110011'		;//4
              			MOVWF	PORTD			;
              			RETURN			;
       D_FIVE:
              			MOVLW	b'01011011'		;//5
              			MOVWF	PORTD			;
              			RETURN;
       D_SIX:
              			MOVLW	b'01011111'		;//6
              			MOVWF	PORTD			;
              			RETURN			;
       D_SEVEN:
              			MOVLW	b'01110000'		;//7
              			MOVWF	PORTD			;
              			RETURN			;
       D_EIGHT:
              			MOVLW	b'01111111'		;//8
              			MOVWF	PORTD			;
              			RETURN;
       D_NINE:		
              			MOVLW	b'01111011'		;//9
              			MOVWF	PORTD			;
              			RETURN		;
       TURN_NINE:
              			MOVLW	d'10'			;
              			MOVWF	TEMP			;
              			GOTO	BASE			;

Para los delays usamos una lógica de un ciclo usando la instrucción DECFSZ y llamadas a partes del código con GOTO, el ciclo tiene la lógica n*(3*x)*x, ya que cada instrucción dura un microsegundo, ocupamos que se hagan 1000000 de instrucciones para que dure un segundo por lo que n tendrá el valor de 6 y x el valor de 236; donde se haría 1002528 instrucciones acercándose al segundo. Para visualizar en que velocidad estamos pusimos 5 leds en el puerto C y mandamos un 1 a su respectivo led.

       DELAY_1S:
              			MOVLW	b'00100000'
              			MOVWF	PORTC			
           			MOVLW	d'6'			;
              			MOVWF	TM1			;
              			MOVLW	D'236'			;
              		T3:	MOVWF	TM2			;
              		T2:	MOVWF	TM3			;
              		T1:	DECFSZ	TM3			;
              			GOTO	T1		        ;
              			DECFSZ	TM2			;
              			GOTO	T2			;
              			DECFSZ	TM1			;
              			GOTO	T3			;
              			RETURN				;

Una vez teniendo el delay de un segundo lo único que se hacia es que se implementaba la mismo logica de codigo, solo cambiamos nuestra n y x para que nos del valor correcto. En el caso del delay de 5 segundos solo cambiamos el valor de n a '30' y x que3da en 236, para que sea hagan 5 veces mas instrucciones por lo que duraría 5 veces mas el segundo, dándonos los 5 segundos.

             	DELAY_5S:
             			MOVLW	b'01000000'
             			MOVWF	PORTC
             			MOVLW	d'30'			;
             			MOVWF	TM1			;
             			MOVLW	D'236'			;
             		T35:	MOVWF	TM2			;
             		T25:	MOVWF	TM3			;
             		T15:	DECFSZ	TM3			;
             			GOTO	T15		        ;
             			DECFSZ	TM2			;
             			GOTO	T25			;
             			DECFSZ	TM1			;
             			GOTO	T35			;
             			MOVLW	b'00000000'
             			MOVWF	PORTC			
             			RETURN				;

Para el delay de 10 segundos, ocupamos que sea el doble de 5 segundos por que n valdrá 60, x se mantiene en 236.

             	DELAY_10S:
             			MOVLW	b'10000000'
             			MOVWF	PORTC			
             			MOVLW	d'60'			;
             			MOVWF	TM1			;
             			MOVLW	D'236'			;
             		T310:	MOVWF	TM2			;
             		T210:	MOVWF	TM3			;
             		T110:	DECFSZ	TM3			;
             			GOTO	T110		        ;
             			DECFSZ	TM2			;
             			GOTO	T210			;
             			DECFSZ	TM1			;
             			GOTO	T310			;
             			RETURN				;

Para los delays pequeños, en el caso del delay de .5 segundos; usamos la logica de los delays anteriores. Por lo que si queremos la mitad del tiempo nuestra n tendra la mitad del valor que tiene en el delay de un segundo; en este caso n vale 3 y x aun se mantiene en 236.

             	DELAY_500mS:
             			MOVLW	b'00000010'
             			MOVWF	PORTC
             			MOVLW	d'3'			;
             			MOVWF	TM1			;
             			MOVLW	D'236'			;
             		T305:	MOVWF	TM2			;
             		T205:	MOVWF	TM3			;
             		T105:	DECFSZ	TM3			;
             			GOTO	T105		        ;
             			DECFSZ	TM2	    		;
             			GOTO	T205			;
             			DECFSZ	TM1			;
             			GOTO	T305			;
             			RETURN				;

En el caso del delay de .1 segundos, si seguíamos la misma lógica que los delays anteriores, n valdría .6 y x valdría 236; pero para evitar usar números decimales n lo dejamos el valor de 6 y despejando nos da que x debe valer 75 para que el delay tarde .1 segundos.

             DELAY_100mS:
             			MOVLW	b'00000001'
             			MOVWF	PORTC	
             			MOVLW	d'6'			;
             			MOVWF	TM1			;
             			MOVLW	D'75'			;
             		T301:	MOVWF	TM2			;
             		T201:	MOVWF	TM3			;
             		T101:	DECFSZ	TM3			;
             			GOTO	T101		        ;
             			DECFSZ	TM2			;
             			GOTO	T201			;
             			DECFSZ	TM1			;
             			GOTO	T301			;
             			RETURN				;

Para poder cambiar de velocidad, creamos una variable llamada IDX, IDX tomara valores del 0 al 4, para la velocidad mas rápida (la de .1 segundos) IDX tomara el valor de 0; y mientras se incremente IDX mas se incrementara el tiempo de espera. Por ende; nuestra velocidad mas lenta IDX tendrá el valor de 4.

El reto que tuvimos fue el de evitar que IDX tuviera un valor mayor a 4 y menor a 0; por que lo que creamos dos subrutinas; una para subir la velocidad y otra para bajarla; para la subrutina DEC_VEL; IDX no puede pasar de 4 por lo que mandamos un 4 a W y restamos ese 4 a IDX; de esta manera podemos usar la instrucción BZ que nos mandara a la subrutina INC_VEL evitando así que nuestro IDX sea mayor a 4; en caso de no tener un 4 nuestra IDX podrá aumentar en caso de estar presionado el botón.

             	DEC_VEL:
             			MOVLW	0x04
             			SUBWF	IDX,0
             			BZ	INC_VEL
             			BTFSC	PORTB,RB7
             			INCF	IDX
             			RETURN

En caso de la subrutina INC_VEL; usamos la misma lógica solo mandando un 0 ahora a w para evitar que IDX tenga un valor menor a 0.

             	INC_VEL:
             			MOVLW	0x00
             			SUBWF	IDX,0
             			BZ	DEC_VEL
             			BTFSC	PORTB,RB6
             			DECF	IDX
             			RETURN

Una vez teniendo nuestras subrutinas que cambiaran el valor de nuestra IDX, creamos la subrutina con la que IDX llamara al delay que queramos implementar; para esto decidimos usar la instruccion BZ para que mandar a llamar el delay dependiendo del valor de IDX.

             VEL_TABLE:
             			MOVLW	0x00
             			SUBWF	IDX,0
             			BZ	DELAY_100mS
             			MOVLW	0x01
             			SUBWF	IDX,0
             			BZ	DELAY_500mS
             			MOVLW	0x02
             			SUBWF	IDX,0
             			BZ	DELAY_1S
             			MOVLW	0x03
             			SUBWF	IDX,0
             			BZ	DELAY_5S
             			MOVLW	0x04
             			SUBWF	IDX,0
             			BZ	DELAY_10S
             			RETURN

Por ultimo modificamos nuestra base; usando la instruccion BTSFC checamos que cuando nuestros botones en RB7(para decrementar la velocidad) y en RB6(Para aumentar la velocidad); llamen a sus respectivas subrutinas que les permite modificar el valor de IDX y asi llamar a la subrtuina VEL_TABLE para que se implemente el delay correcta antes de que nuestro display cambie de numero.

             BASE:
             			MOVF	TEMP,W			;
             			BZ	TURN_NINE 		;
             			DECF	TEMP			;
             			BTFSC	PORTB,RB7
             			CALL	DEC_VEL			
             			BTFSC	PORTB,RB6
             			CALL	INC_VEL
             			CALL	VEL_TABLE		
             			CALL	DECODE			;
             			GOTO 	BASE			;infinite loop

Preguntas y resultados

1. ¿Generaste los retrasos de forma individual? ¿Qué harías si tuvieras que hacer 100 diferentes retrasos? Si pudimos generar los retrasos de forma indivual, por lo que si tuviéramos que implementar 100 diferentes retrasos no tendríamos ningún problema ya que nuestra IDX puede llegar a tener un valor aun mayor que 100; y solo tendríamos que crear las subrutinas correspondientes.

2. Un problema que tuvimos es la hora de implementar la practica en físico; nuestro cristal de 4Mhz estaba descompuesto, por lo que tuvimos que usar un cristal interno del microcontralador y los delays son mas lentos.

Video de la implementacion fisica. https://www.youtube.com/watch?v=aPtAVMhDwII

⚠️ **GitHub.com Fallback** ⚠️