TODOPIC
Microcontroladores PIC => Primeros pasos - Iniciación a los microcontroladores => Mensaje iniciado por: Joga en 07 de Mayo de 2008, 10:57:43
-
Bueno, pues inicio este post para ir poniendo mis progresos y así me voy animando yo también.
He probado el en circuito el programa del led que parpadea y me me funcionado a la primera :-/.
No pondo el código porque está en muchos sitios y solo me he limitado a copiarlo, pero para los siguientes ejercicios: un par de leds, el del "coche fantastico" y esas cosillas, me fijaré en el esquema del montaje y el código lo intentaré hacer yo, publicándolo para que digais que os parece o si alguien empieza de cero como yo, compartamos experiencias.
Un saludo.
-
Bueno, pues inicio este post para ir poniendo mis progresos y así me voy animando yo también.
He probado el en circuito el programa del led que parpadea y me me funcionado a la primera :-/.
No pondo el código porque está en muchos sitios y solo me he limitado a copiarlo, pero para los siguientes ejercicios: un par de leds, el del "coche fantastico" y esas cosillas, me fijaré en el esquema del montaje y el código lo intentaré hacer yo, publicándolo para que digais que os parece o si alguien empieza de cero como yo, compartamos experiencias.
Un saludo.
Joga, te felicito, todo aporte por menor que parezca ayudará a alguien. ;) ;)
-
Opino igual.
Bien está que al principio uno se fije en los programas de los demás pero luego hay que soltarse y hacerlos uno mismo, de lo contrario no se aprende.
Adelante.
-
Saludos Joga! Me parece excelente este hilo que has iniciado :-/ ... vas a aprender y a divertirte muchísimo!
Y aquí estaremos para colaborar en lo que se pueda...
Nos leemos! :mrgreen:
-
Pues voy poniendo el esquema de los dos primeros ejercicios que voy a hacer:
El primero se trata de que un led (led1) se encienda, despues de 1s se encienda el otro (led2), se apaga el led1 y despues el led2, volviendo a empezar de nuevo.
Por lo que tendré que crear una rutina de retardo.
(http://img102.imageshack.us/img102/2067/2ledshm8.th.jpg) (http://img102.imageshack.us/my.php?image=2ledshm8.jpg)
Y el segundo se trata de hacer "el coche fantastico", además de otros 2 o 3 efectos diferentes que se cambiaran mediante la interrupción producida por el pulsador.
Lo de los consumos, no lo tengo muy claro: se supone que en modo source el puerto B soporta 100mA, y que los leds-rojos consumen unos 20mA, por lo que tengo 5 leds x 20mA = 100mA + la corriente que entrará en modo sumidero al RB0. ¿no?. No se si con unas resistencias mayores en los leds disminuiría el consumo, ni si la resistencia de 10k en el pulsador es la más adecuada.
En este caso los retardos los intentaré implementar mediante el TRM0. :-)
(http://img229.imageshack.us/img229/9158/5ledsed2.th.jpg) (http://img229.imageshack.us/my.php?image=5ledsed2.jpg)
Un saludo.
P.D.: "sumidero, source, interrupciones...", si parece que se de lo que hablo. :mrgreen:.
-
Felicitaciones Joga! :-/
Bueno solo te quería comentar que yo siempre uso resistencias de 470 ohms para los leds, y me funcionan de lo lindo... así se obtiene buena luminosidad en los leds y se protege al pic también. De todos modos si estoy equivocado ya algún experto lo aclarará...
Y en cuanto a lo de los pulsadores, sería bueno que le colocaras condensadores para evitar los efectos rebote...
Ok es todo, nos leemos! :mrgreen:
-
el efecto rebote lo podrias solucionar por software, al momento que sensas el estado del pulsador, cuando entre a la rutina del mismo espera un tiempo(us o ms) y vuelves preguntar por el pulsador si se mantiene con el nivel logico que deberia tener al pulsar, entonces no es un rebote. :D espero que se me entienda y si no avisen para poner un ejemplillo :D
-
Totalmente de acuerdo poseidon! :-/
Esa es otra opción para eliminar los rebotes...
Aunque a mí me siguen gustando los condensadores... :D
Ok nos leemos! :mrgreen:
-
Hola, lo que yo utilizo como eliminadores de rebotes y falsas señales en mis diseños, generalmente sometidos a ambientes críticos, es una protección por HW que puede variar desde un simple pasabajos de frecuencia de corte baja (10 Hz por ejemplo) hasta todo un circuito de protección con TVS, diodos schkotty, inductores y hasta optoacopladores, pero el filtro RC es siempre fundamental para mi.
Por otro lado, tambien utilizo un filtrado por SW de dos formas, primero genero un filtro pasabajos para cada entrada de pulsador, no lo implemento con delays porque es una perdida de tiempo importante, generalmente lo hago utilizando variables incrementales referidas a un timer y comprobandolas cada ciclo, porque de todas formas no necesitas exactitud a la hora de determinar la frecuencia de corte del filtro digital, puede estar entre los 50 y los 5 Hz tranquilamente. Luego hago un muestreo del estado del puerto anterior y lo compruebo con el estado actual, para que la deteccion sea por flancos y no por estados, que son menos confiables. He tenido a veces que realizar 2 comprobaciones de estado, porque el ruido era tan fuerte que me cambiaba los bits de estado de la entrada.
Nos estamos escribiendo.
-
Saludos!
Ya me estoy acostumbrando a las superexplicaciones del Dr. Gonzalo :D
Viejo gracias por compartir tu experiencia! :-/
Nos leemos! :mrgreen:
-
Gracias por el cumplido firepic, tambien todos aqui en el foro te agradecemos tu aporte. :-) :-) :-)
Un saludo desde Argentina.
-
Gracias a todos por las respuestas. He terminado el primer ejercicio y lo he probado en circuito satisfactoriamente :mrgreen:.
La rutina de retardo no me ha salido exacta, me da 1,003 segundos, a mi me vale por ahora. :D.
Aquí os pongo el código:
;DIRECTIVAS------------------------------------------------------------------------
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ;Configuración del grabador
LIST P=16F84A
INCLUDE <P16F84A.INC>
;DECLARACION DE VARIABLES-----------------------------------------------------------
CBLOCK 0X0C ;Creo 3 contadores de memoria para el retardo.
Cont_A ; Cuenta 500 uS
Cont_B
Cont_C
ENDC
;-----------------------------------------------------------------------------------
ORG 0
Inicio
bsf STATUS,RP0 ;Paso al banco 1
clrw ;Pongo a 0 el registro W
movwf TRISB ; Configuro como salida el puertoB.
bcf STATUS, RP0 ;Vuelvo al banco 0
;Aquí se enciende y apagan los leds.
Principal
bsf PORTB,0 ;Pone 1 en RB0 (enciende el LED 1)
call Retardo_1s ;Espera 1 segundo.
bsf PORTB,1 ;Pone 1 en RB1 (enciende el LED 2)
call Retardo_1s
bcf PORTB,0 ;Pone a 0 el RB0 (apaga el LED 1)
call Retardo_1s
bcf PORTB,1 ;Pone a 0 el RB1 (apaga el LED 2)
call Retardo_1s
goto Principal
;Rutina de retardo.
Retardo_1s
movlw .10 ;Aquí se cargan Cont_C a 10
movwf Cont_C
T100mS
movlw .199 ;Aquí se carga Cont_B a 199
movwf Cont_B
T500uS
movlw .166
movwf Cont_A ;Aquí se carga Cont_A a 166
Bucle_int
decfsz Cont_A,F ;Comienza a decrementar.
goto Bucle_int
nop
nop ;Aquí termina el bucle con Cont_A y tanscurren 500uS
decfsz Cont_B,F ;Decrementa Cont_B
goto T500uS ;Cuando Cont_B llega a 0, han transcurrido unos 100mS aprox.
decfsz Cont_C,F ;Decrementa Cont_C
goto T100mS ;Cuando Cont_C llega a 0 ha transcurrido 1 segundo aprox.
return ;vuelve a donde se hizo la llamada.T
END
Un saludo.
-
Solo un pequeño comentario. Para realizar el retardo de 1s has usado 3 contadores anidados y para calcular sus valores supongo que habrás empleado algún programa específico para esto.
También puedes conseguir retardos usando el TMR0. El uso de un TMR para los retardos es muy interesante desde el punto de vista de que el PIC no tiene porqué estar esperando sin hacer nada a que termine el retardo, usando el TMR0 puede estar haciendo otras cosas.
Un saludo
-
Es cierto Joga! :-)
Trata de usar mejor los propios timers del pic...
Bueno lo que te dice el maestro pocher sobre hacer otras cosas a la vez es cuando usas también interrupciones...
Pero aunque no trabajes con interrupciones igual es mejor porque te permite hacer la pausa usando menos código, solo configuras el timer con las opciones apropiadas para tu retardo, lo cargas con el valor correcto y luego simplemente te queda evaluar el estado de t0if para saber cuándo ocurrió el desbordamiento... y la pausa te queda mucho más exacta...
De todos modos por ahí conseguirá mucha más información de cómo usar el timer...
Ok nos leemos! :mrgreen:
-
El calculo para las interrupciones lo he hecho yo manualmente, sin ningún programa (por eso no me ha salido exacto del todo), y lo que me comentáis de las interrupciones y el TMR, lo tengo para el próximo ejercicio, si leéis mas arriba veréis que dige que este primero lo haría así, y para el segundo implementaría interrupciones y el TMR (lo digo sin acritud ninguna :mrgreen:). Primero hay que hacerlo mas difícil y engorroso para luego apreciar las características que te permiten hacerlo mas cómodamente, como las señales para motores paso a paso que he oído que son un coñazo en este pic, así cuando cambies a un pic que implementa pines para esto, lo valoras de verdad. Y disfrutas al ver como consigues lo mismo con menos trabajo. :-/
Un saludo.
-
Tienes razón Joga! :-/
Creo que pocher y yo sólo queríamos que usaras todas las herramientas, pero veo que no se te ha escapado nada! :mrgreen:
Usando un símil venezolano, es como aprender a hacer primero arepas a mano y luego a usar el tostiarepas...
Siempre es importante también saber hacerlas a mano! :D
Ok nos leemos! :mrgreen:
-
Ya he terminado el del coche fantastico, que también tiene dos secuencias más que se cambian al pulsar el pulsador.
Aquí pongo el esquema final.
(http://img140.imageshack.us/img140/4136/5ledseh3.th.jpg) (http://img140.imageshack.us/my.php?image=5ledseh3.jpg)
Y aquí el código:
;DIRECTIVAS------------------------------------------------------------------------
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ;Configuración del grabador
LIST P=16F84A
INCLUDE <P16F84A.INC>
;DECLARACION DE VARIABLES-----------------------------------------------------------
CBLOCK 0X0C
NumP ;Número de pulsaciones del pulsador.
NumR ;Número de repeticiones
NumT ;Número de repeticones para el tiempo.
ENDC
#DEFINE Pulsador PORTB,0
#DEFINE Led1 PORTB,1
#DEFINE Led2 PORTB,2
#DEFINE Led3 PORTB,3
#DEFINE Led4 PORTB,4
#DEFINE Led5 PORTB,5
;-----------------------------------------------------------------------------------
ORG 0
goto Inicio
ORG 4 ;Aquí acude el programa cada vez que hay una interrupcion.
goto Interrupcion
Inicio
bsf STATUS,RP0 ;Paso al banco 1
movlw b'00000001'
movwf TRISB ;Pongo el pin RB0/INT como entrada y los demás como salidas.
movlw b'00000111' ;Selecciono el preescaler a 256
movwf OPTION_REG
bcf STATUS, RP0 ;Vuelvo al banco 0
movlw b'10010000' ;Habilito solo las interrupciones por INT.
movwf INTCON
call Reseteo ; Me aseguro de que estén apagados los leds.
;Aquí se enciende y apagan los leds.
Principal
sleep ;Duerme hasta que no se produzca una interrupcion.
goto Principal
TMR0_60ms EQU .21
TMR0_20ms EQU .177
Timer0_20ms
movlw TMR0_20ms ;Cargo el TMR0 para 20ms
movwf TMR0
bcf INTCON,T0IF ;Resetea el flag de desbordamiento del TMR0
Timer0_Desbordado1
btfss INTCON,T0IF ;Compruebo si se ha desbordado el TMR0.
goto Timer0_Desbordado1 ; No se ha desbordado.
return ; Se ha desborda
Timer0_120ms
movlw .2
movwf NumT ;Realizo 2 repetiones para lograr 120ms aprox.
movlw TMR0_60ms ;Cargo el TMR0 para 60ms
movwf TMR0
Reset_TMR0
bcf INTCON,T0IF ;Resetea el flag de desbordamiento del TMR0
Timer0_Desbordado
btfss INTCON,T0IF ;Compruebo si se ha desbordado el TMR0.
goto Timer0_Desbordado ; No se ha desbordado.
decfsz NumT,F
goto Reset_TMR0
return ; Se ha desbordado.
Interrupcion
call Timer0_20ms ;Espero 20ms por si es un rebote.
btfsc Pulsador ;Compruebo si está pulsado
goto Fin_Interrupcion ;Ha sido un rebote, por lo que sale.
incf NumP,F ;No ha sido un rebote, incremento NumP.
call Reseteo
movfw NumP
sublw .1
btfsc STATUS,Z ;Compruebo si vale 1
call Coche ;Como es 0 ejecuto el coche fantastico :).
movfw NumP
sublw .2
btfsc STATUS,Z ;Compruebo si vale 2
call Sec2 ;Como es 2 ejecuto la secuencia 2 de los leds.
movfw NumP
sublw .3
btfsc STATUS,Z ;Compruebo si vale 3
call Sec3 ;Como es 3 ejecuto la secuencia 3 de los leds.
Fin_Interrupcion
bcf INTCON,INTF ;Limpio el flag de reconocimiento de interrupcion INT.
retfie ;Retorna y habilita las interrupciones.
Reseteo
movlw .5 ;Establezco 5 repeticiones.
movwf NumR
bcf Led1 ; Me aseguro de que estén apagados los leds
bcf Led2 ; antes de empezar la secuencia.
bcf Led3
bcf Led4
bcf Led5
return
Coche
bsf Led1 ;Enciendo el led1
call Timer0_120ms ;Espero
bcf Led1 ;Apago el led1
call Timer0_120ms ;Espero
bsf Led2 ;Enciendo el led2
call Timer0_120ms ; ..............
bcf Led2
call Timer0_120ms
bsf Led3
call Timer0_120ms
bcf Led3
call Timer0_120ms
bsf Led4
call Timer0_120ms
bcf Led4
call Timer0_120ms
bsf Led5
call Timer0_120ms
bcf Led5
call Timer0_120ms
bsf Led4
call Timer0_120ms
bcf Led4
call Timer0_120ms
bsf Led3
call Timer0_120ms
bcf Led3
call Timer0_120ms
bsf Led2
call Timer0_120ms
bcf Led2
call Timer0_120ms
bsf Led1
call Timer0_120ms
decfsz NumR,F
goto Coche
bcf Led1 ;Apago el Led1, puesto que se quedaría encendido al salir.
return
Sec2
bsf Led1
call Timer0_120ms
bsf Led2
call Timer0_120ms
bsf Led3
call Timer0_120ms
bcf Led1
call Timer0_120ms
bcf Led2
call Timer0_120ms
bcf Led3
call Timer0_120ms
bsf Led3
call Timer0_120ms
bsf Led4
call Timer0_120ms
bsf Led5
call Timer0_120ms
bcf Led5
call Timer0_120ms
bcf Led4
call Timer0_120ms
bcf Led3
call Timer0_120ms
decfsz NumR,F
goto Sec2
return
Sec3
bsf Led1
bsf Led5
call Timer0_120ms
bcf Led1
bcf Led5
call Timer0_120ms
bsf Led2
bsf Led4
call Timer0_120ms
bcf Led2
bcf Led4
call Timer0_120ms
bsf Led3
call Timer0_120ms
bcf Led3
call Timer0_120ms
bsf Led3
call Timer0_120ms
bcf Led3
call Timer0_120ms
decfsz NumR,F
goto Sec3
movlw .0 ;Pongo a 0 NumP para inicializar la secuencia de pulsaciones.
movwf NumP
return
END
Al principio no me funcionaba, y resulta que no habia hecho bien la rutina para el TMR y en vez de 120ms aproximados, me daba 7 uS :D. (Como pa verlo).
Lo que me he dado cuenta es que al apagar la fuente de alimentacion se pone a encerder leds como si lo hubiera pulsado.
Le faltaría también una optimizacion en las partes donde se enciende los leds, pero lo dejo para otra vez. De momento voy a pensar en alguna practiva con displays de siete segmentos :mrgreen:.
Un saludo.
-
Debido a que tengo poco tiempo para dedicárselo a la electrónica, voy a ir más rápido y he empezado con C a ver si hago algún proyecto y voy aprendiendo mientras lo realizo.
Aquí pongo el código de un display de 7 segmentos que muestra del 0-9, de A-F y el punto, cambiando cada vez que se pulsa un botón.
;DIRECTIVAS------------------------------------------------------------------------
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ;Configuración del grabador
LIST P=16F84A
INCLUDE <P16F84A.INC>
;DECLARACION DE VARIABLES-----------------------------------------------------------
CBLOCK 0X0C
Pos ;Posicion en la tabla.
NumT ;Número de repeticones para el tiempo.
ENDC
#DEFINE Pulsador PORTA,2
;-----------------------------------------------------------------------------------
ORG 0
goto Inicio
Inicio
bsf STATUS,RP0 ;Paso al banco 1
clrf TRISB ;Configuro el puerto B como salida.
movlw b'00000100' ;Configuro RA2 como entrada.
movwf TRISA
movlw b'10000111' ;Desactivo resistencias Pull-Up, Pre-escaler a 256
movwf OPTION_REG
bcf STATUS, RP0 ;Vuelvo al banco 0
movlw b'00000000' ;Desabilito las interrupciones.
movwf INTCON
movlw .0 ;Pongo a 0 Pos
movwf Pos
clrf PORTB ;Me aseguro que este el puerto B apagado.
;Aquí se enciende y apagan los leds.
Principal
btfsc Pulsador ;Compruebo si está pulsado
goto Principal ;No se ha pulsado.
call Timer0_20ms ;Espero 20ms por si es un rebote.
btfsc Pulsador ;Vuelvo a comprobar
goto Principal ;Era un rebote
movfw Pos ;No era un rebote.
call Tabla
movwf PORTB ;Muestro el digito seleccionado en la tabla.
call Timer0_300ms ;Espero para que no salte varios digitos de una pulsación.
incf Pos ;Incremento Pos para visualizar el siguiente digito.
movfw Pos
sublw .17
btfss STATUS,Z ;Compruebo si vale 17
goto Principal
movlw .0 ;Pongo a 0 Pos
movwf Pos
goto Principal
TMR0_20ms EQU .177
TMR0_60ms EQU .21
Timer0_20ms
movlw TMR0_20ms ;Cargo el TMR0 para 20ms
movwf TMR0
bcf INTCON,T0IF ;Resetea el flag de desbordamiento del TMR0
Timer0_Desbordado
btfss INTCON,T0IF ;Compruebo si se ha desbordado el TMR0.
goto Timer0_Desbordado ; No se ha desbordado.
return
Timer0_300ms
movlw .5
movwf NumT ;Realizo 10 repetiones para lograr 300ms aprox.
movlw TMR0_60ms ;Cargo el TMR0 para 60ms
movwf TMR0
Reset_TMR0
bcf INTCON,T0IF ;Resetea el flag de desbordamiento del TMR0
Timer0_Desbordado1
btfss INTCON,T0IF ;Compruebo si se ha desbordado el TMR0.
goto Timer0_Desbordado1 ; No se ha desbordado.
decfsz NumT,F
goto Reset_TMR0
return
Tabla
addwf PCL,F
DT 3Fh,06h,5Bh,4Fh,66h,6Dh,7Dh,07h,7Fh,67h,77h,7Ch,39h
DT 5Eh,79h,71h,80h
END
Y Aquí en C :mrgreen:
#include <16F84A.h>
#FUSES NOWDT //Deshabilito el wardog
#FUSES XT //Selecciono oscilador de cuarzo
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //No le pongo protección
#use delay(clock=4000000)
#use standard_io(B)
#use standard_io(A)
#define Pulsador PIN_A2
void main()
{
char Pos = 0; //Posicion en la tabla.
int Tabla[17] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67,0x77,
0x7C,0x39,0x5E,0x79,0x71,0x80}; //Números 0-9, letras A-F y el punto.
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
port_b_pullups(FALSE);
set_tris_b(0);
set_tris_a(0b00000100);
disable_interrupts(GLOBAL); //todas las interrupciones desactivadas
output_b(0); //Me aseguro de que esté apagado el display
do{
if (!input(Pulsador))
{
delay_ms(20);
if (input(Pulsador) == 0)
{
output_b(Tabla[Pos]);
delay_ms(300); ;Espero para poder ver la secuencia correctamente .
Pos++;
if (Pos == 17)
{
Pos = 0; ;Como ha llegado al punto, le indico que vuelva a empezar.
}
}
}
}while(true);
}
Aprovecho para comentaros que pienso pasarme a un pic 18F, aunque parezca precipitado, quiero aprenderlo mientras hago un proyecto que más tarde pondré en la sección correspondiente de este foro, de momento tengo claro que va a tener una pantalla LCD 2x16, unos leds, un par de pulsadores y no se si un display de 7 segmentos, e irá conectado al ordenador por usb. Pero no se cual comprar, si el 18F2550 o el 18F4550 ya que se diferencian muy poco de precio. A ver que me recomendáis vosotros.
Un saludo.