Problema circuito con PIC 16F628A

Hola amigos...

Tengo un problema con un circuito que realice como trabajo sobre "la obsolescencia programada", para lo cual hice un circuito basado en un PIC 16F628A, el cual tiene 2 pulsadores, uno para encender y apagar un led, y otro para recetear una dirección especifica de la memoria EEPROM.

Función del circuito: En el código programe que el LED debe encender 10 veces y después de esas 10 veces "se daña" el circuito, realmente lo que hago es guardar en la memoria EEPROM del PIC el conteo de cuantas veces se ha encendido el LED, cuando llega a 10 se va a un bucle en e cual el LED siempre va a estar apagado, y donde va a estar revisando el estado lógico del segundo botón, donde si este es pulsado, la dirección donde guardo ese conteo se pone en 0 para iniciar nuevamente el conteo...

Simulado me funciona perfectamente, en proteus.

El problema esta cuando monto el circuito en la protoboard, cuando lo hago no hace absolutamente nada!!no enciende el LED no hace nada!!

Alguien podria decirme que sucede gracias, espero sus respuestas...

Adjunto archivo .ASM .HEX y simulacion en proteus...
 

Adjuntos

  • Obsolesencia Programada.rar
    27.8 KB · Visitas: 19
Última edición:
Hola cguerrero1205. Por lo que puedo ver en un vistazo rápido a tú programa le pasa varias cosas:

Primero, el micro de fábrica el puerto A viene configurado como comparadores (si no me equivoco y me acuerdo bien) y tú no lo configuras como salidas/entradas digitales.

Segundo, por lo que veo, no tienes rutina "anti-rebotes" para los pulsadores, por lo que en una sola pulsada puedes tener 5-10 pulsos del mismo pulsador haciendo que el funcionamiento sea erróneo.

Tercero, no tienes configurada la dirección de las interrupciones, y aunque tú no la uses nunca está de más colocarla, y si no usas las interrupciones, no pongas comandos para la misma (mira la parte de lectura/escritura en la eeprom) y en la configuración general desabilítalas a todas (CLRF intcon).

Puedes empezar reformado esto y veremos que sucede.

Un saludo.

Atte. CARLOS.
 
Hola cguerrero1205. Por lo que puedo ver en un vistazo rápido a tú programa le pasa varias cosas:

Primero, el micro de fábrica el puerto A viene configurado como comparadores (si no me equivoco y me acuerdo bien) y tú no lo configuras como salidas/entradas digitales.

Segundo, por lo que veo, no tienes rutina "anti-rebotes" para los pulsadores, por lo que en una sola pulsada puedes tener 5-10 pulsos del mismo pulsador haciendo que el funcionamiento sea erróneo.

Tercero, no tienes configurada la dirección de las interrupciones, y aunque tú no la uses nunca está de más colocarla, y si no usas las interrupciones, no pongas comandos para la misma (mira la parte de lectura/escritura en la eeprom) y en la configuración general desabilítalas a todas (CLRF intcon).

Puedes empezar reformado esto y veremos que sucede.

Un saludo.

Atte. CARLOS.



Hola Carlos...

El primer punto si lo entiendo, ahora busco el código para configurar los comparadores como I/O digitales, tienes razón en eso, se me olvidó configurarlo.

El segundo, si tengo una rutina antirebote, si te fijas en el .asm hay una subrutina q se llama "AE_LED, AA_LED y AD_LED" si miras esas 3 rutinas funcionan como antirebote, tambien puedes mirar el archivo de proteus, verás q no se hacen pulsos de seguidos, sólo uno a la vez.

Lo tercero, la verdad no te entendí nada! :confused: podrías explicarme mejor esa parte??

Gracias por tu respuesta :thumbup: :D
 
Hola:

Por si acaso, los antirrebotes, un ejemplo:
Código:
Inicio
     bsf        STATUS,RP0            ; Acceso al Banco 1.
    bsf        Pulsador            ; La línea RA4 se configura como entrada.
    bcf        LED                    ; Se configura como salida.
    bcf        STATUS,RP0            ; Acceso al Banco 0.
    bcf        LED                    ; En principio diodo LED apagado.
Principal
    btfsc    Pulsador            ; ¿Pulsador presionado?, ¿(Pulsador)=0?
    goto    Fin                    ; No. Vuelve a leerlo.
    call    Retardo_20ms        ; Espera que se estabilicen los niveles de tensión.
    btfsc    Pulsador            ; Comprueba si es un rebote.
    goto    Fin                    ; Era un rebote y sale fuera.
    btfsc    LED                    ; Testea el último estado del LED.
     goto    EstabaEncendido
EstabaApagado
    bsf        LED                    ; Estaba apagado y lo enciende.
    goto    EsperaDejePulsar
EstabaEncendido
    bcf        LED                    ; Estaba encendido y lo apaga.
EsperaDejePulsar
    btfss    Pulsador            ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar    ; No. Espera que deje de pulsar.
Fin
    goto    Principal

    INCLUDE <RETARDOS.INC>
    END
En cuanto a la absolescencia programada. Ahora estoy practicando un poco con el PIC16F886. Tiene la opción de seleccionar la EEPROM o la Flash o memoria programa. En este mismo foro, me han contado hace tiempo que modificar así mismo la memoria programa o Flash, es para hacr cosas de absolescencia programada. Aunque me parece más fácil desde la EEPROM.

¿Qué pasa cuando el PIC que te exige el cliente no tiene EEPROM interna?

Pues usar la propia Flash, los últimos PIC tiene esa posibilidad, el pobre PIC16F84A no la tiene, PIC16F88 no se si lo tiene, pero el 16F886 y 16F887 si lo emplean. En la hoja de datos lo explica muy bien, también me he enterado gracias a este libro que compré.

Ver portada

Saludo.
 
Hola:

Por si acaso, los antirrebotes, un ejemplo:
Código:
Inicio
     bsf        STATUS,RP0            ; Acceso al Banco 1.
    bsf        Pulsador            ; La línea RA4 se configura como entrada.
    bcf        LED                    ; Se configura como salida.
    bcf        STATUS,RP0            ; Acceso al Banco 0.
    bcf        LED                    ; En principio diodo LED apagado.
Principal
    btfsc    Pulsador            ; ¿Pulsador presionado?, ¿(Pulsador)=0?
    goto    Fin                    ; No. Vuelve a leerlo.
    call    Retardo_20ms        ; Espera que se estabilicen los niveles de tensión.
    btfsc    Pulsador            ; Comprueba si es un rebote.
    goto    Fin                    ; Era un rebote y sale fuera.
    btfsc    LED                    ; Testea el último estado del LED.
     goto    EstabaEncendido
EstabaApagado
    bsf        LED                    ; Estaba apagado y lo enciende.
    goto    EsperaDejePulsar
EstabaEncendido
    bcf        LED                    ; Estaba encendido y lo apaga.
EsperaDejePulsar
    btfss    Pulsador            ; ¿Dejó de pulsar?. ¿(Pulsador)=1?
    goto    EsperaDejePulsar    ; No. Espera que deje de pulsar.
Fin
    goto    Principal

    INCLUDE <RETARDOS.INC>
    END


Voy a tratar de utilizar este anti rebote porque ya configuré los los comparadores como I/O digitales y si "funcionó"
Ahora el problema es que no cuenta los 10 pulsos.
Cuando presiono el botón el LED enciende pero se apaga de una vez.
A veces enciende y no se apaga, creo que es por el anti rebote.
 
Última edición por un moderador:
Hola cguerrero1205, perdona, voy a tratar de expresarme de manera entendible:

Lo tercero, la verdad no te entendí nada! :confused: podrías explicarme mejor esa parte??

Gracias por tu respuesta :thumbup: :D

Tu usas la dirección de inicio:
ORG 00
GOTO INICIO

Y esto está perfecto, pero también tienes la dirección de las interrupciones:
ORG 04
GOTO XXXX

Y aunque tu no uses las interrupciones en este programa, nunca está de más colocar esta dirección, en el ejemplo anterior te redirecciona a la sub-rutina de interrupciones nombrada XXXX, pero si tú no usas interrupciones usarías lo siguiente:

ORG 04
CLRF INTCON
RETURN

Con lo anterior te aseguras que por cualquier "error" de programación desabilitas las interrupciones y continuas como si no hubiera pasado nada.

Más allá de lo anterior, si no usas las interrupciones siempre es bueno desactivarlas al momento de la configuración general del micro y o en el mismo inicio del programa:
ORG 00
CLRF INTCON
GOTO INICIO

Y de no usar las interrupciones, por "seguridad" a la hora de escribir el programa, no realizas ningún tipo de operación sobre los comandos de interrupción, ya que esto puede inducir a un comando erróneo (por ejemplo activando alguna de las mismas) y te aseguro que después se complica bastante encontrar el problema y solucionarlo (porque no sabes por donde viene el error ya que no estas "usando" las interrupciones)

Todo esto a modo de compartir experiencias y "facilitarle la vida" a un entusiasta de los micros, lo que te acabo de comentar no lo encontraras en los libros, pero para un principiante (como yo lo e sido en un tiempo y e tenido estos problemas) seguro le resuelve posiblemente futuros dolores de cabeza.

Yo de implementar "la obsolescencia programada" la haría con la EEPROM (la tienen todos los micros actuales) y la colocaría en la ante última posición de la misma (hay micros de la familia 12F que usan la última posición para calibrar el reloj interno).

Espero haber sido más claro esta ves :unsure:

Un saludo.

Atte. CARLOS.
 
Hola cguerrero1205, perdona, voy a tratar de expresarme de manera entendible:



Tu usas la dirección de inicio:
ORG 00
GOTO INICIO

Y esto está perfecto, pero también tienes la dirección de las interrupciones:
ORG 04
GOTO XXXX

Y aunque tu no uses las interrupciones en este programa, nunca está de más colocar esta dirección, en el ejemplo anterior te redirecciona a la sub-rutina de interrupciones nombrada XXXX, pero si tú no usas interrupciones usarías lo siguiente:

ORG 04
CLRF INTCON
RETURN

Con lo anterior te aseguras que por cualquier "error" de programación desabilitas las interrupciones y continuas como si no hubiera pasado nada.

Más allá de lo anterior, si no usas las interrupciones siempre es bueno desactivarlas al momento de la configuración general del micro y o en el mismo inicio del programa:
ORG 00
CLRF INTCON
GOTO INICIO

Y de no usar las interrupciones, por "seguridad" a la hora de escribir el programa, no realizas ningún tipo de operación sobre los comandos de interrupción, ya que esto puede inducir a un comando erróneo (por ejemplo activando alguna de las mismas) y te aseguro que después se complica bastante encontrar el problema y solucionarlo (porque no sabes por donde viene el error ya que no estas "usando" las interrupciones)

Todo esto a modo de compartir experiencias y "facilitarle la vida" a un entusiasta de los micros, lo que te acabo de comentar no lo encontraras en los libros, pero para un principiante (como yo lo e sido en un tiempo y e tenido estos problemas) seguro le resuelve posiblemente futuros dolores de cabeza.

Yo de implementar "la obsolescencia programada" la haría con la EEPROM (la tienen todos los micros actuales) y la colocaría en la ante última posición de la misma (hay micros de la familia 12F que usan la última posición para calibrar el reloj interno).

Espero haber sido más claro esta ves :unsure:

Un saludo.

Atte. CARLOS.

Emmm jajaja creo que entendí. :confused:
Igual ya le agregué esa línea, CLRF intcon, al código en la configuración, después de las líneas donde limpio los puertos, CLRF PORTA y PORTB, ya el circuito si "funciona", el LED enciende, ahora el problema creo que es con el anti rebote, ya que cuando presiono el pulsador, a veces si lo dejo presionado, enciende y apaga el LED de una vez.
Aunque no estoy seguro si el WDT tenga que ver con esto. :confused:
Tengo que averiguar un poco más sobre el tema.

Gracias. :D
 
Última edición por un moderador:
Hola:

El WDT no tiene nada que ver. En cuanto al código de arriba, el de los retardos, por si acaso usa librería de retardos.

Cualquier modificación que hayas hecho su código completo, lo indicas aquí para guiarnos mejor. Si quieres solucionar los retardos y antirrebotes, te centra en ellos, luego lo demás, así poco a poco, el orden lo escoge usted mismo.

Un saludo.
 
Hola cguerrero1205, rutinas anti rebote hay varias, yo creo que en este caso te conviene hacer la que yo nombro de paso a paso, trataré de explicarte como funciona:

En la parte del programa donde el micro espera la presión de alguno de ambos pulsadores colocas la opción:

btfss o btfsc según sea el caso tuyo.

En la sub-rutina donde salta el programa ante la presión del pulsador seleccionado lo primero que haces es colocar una demora de 50ms o superior.
Después de la demora controla que el pulsador se álla "dejado" de pulsar, si no se a dejado vuelves a empezar la sub-rutina actual, y si se a dejado continuas con la sub-rutina y realizas las operaciones necesaria antes de regresar al programa principal.

Esto con ambos pulsadores, y de esta manera tienes dos "funciones" dentro de la misma operación, cuando pulsas los 50mS realizan el anti-rebote y cuando esperas el despulsado te aseguras de no repetir la misma operación varias veces seguidas con solo un pulsado.

Espero te sea de ayuda. Espero los resultados.

Un saludo.

Atte. CARLOS.
 
Última edición:
Hola:

El WDT no tiene nada que ver. En cuanto al código de arriba, el de los retardos, por si acaso usa librería de retardos.

Cualquier modificación que hayas hecho su código completo, lo indicas aquí para guiarnos mejor. Si quieres solucionar los retardos y antirrebotes, te centra en ellos, luego lo demás, así poco a poco, el orden lo escoge usted mismo.

Un saludo.

Muchas gracias por tu ayuda, la tendré en cuenta :thumbup:
 
Hola. Como verán ya le hice las modificaciones que me recomendaron.
Le agregué el anti rebote y configure los comparadores como desactivados.
Pero ahora el circuito no hace nada, no enciende el LED :cry:

¿Qué puede ser? Ayudaaa :confused:
Código:
 __CONFIG _LVP_OFF & _MCLRE_OFF & _BODEN_OFF & _CP_OFF & _PWRTE_Off & _WDT_OFF  & _INTOSC_OSC_NOCLKOUT 



       LIST           P=16F628A        ;Procesador utilizado.

       INCLUDE   <P16F628A.INC>

       ERRORLEVEL   0,   -302      ;suppress bank selection messages



    

;******************************  MAPA DE MEMORIA   ****************************

     CBLOCK    0x20       

     Digito

 Digito10

     CONTADOR

     Data_EE

     Addr_EE

 Contador1

 Contador2

     ENDC



 

;******************************   ZONA DE DATOS    ****************************

#define     Banco0       bcf  STATUS,RP0

#define     Banco1       bsf  STATUS,RP0

#define     LED         PORTA,2





org        0x000

goto       Inicio





Inicio

bsfSTATUS,RP0; Pone a 1 el bit 5 del STATUS. Acceso al Banco 1.

movlwb'00000011'; PORTA CONFIGURADO COMO ENTRADA

movwfTRISA

movlwb'00000000'; PORTB CONFIGURADO COMO SALIDA

movwfTRISB

bcfOPTION_REG,NOT_RBPU  ;Activa las resistencias Pull-Up del Puerto B 

bcfSTATUS,RP0; Pone a 0 el bit 5 de STATUS. Acceso al Banco 0.





;**************************   ZONA DE INSTRUCCIONES    ************************



CLRFPORTA

CLRFPORTB

CLRFDigito;REGISTRO PARA GUARDAR DATO PARA GRABAR EN EEPROM

CLRFINTCON

MOVLW      0x07  ;PARA DESHABILITAR LOS COMPARADORES

    MOVWF     CMCON 

 



CALLLeeEprom



TESTEO



DT"OBSOLESCENCIA PROGRAMADA"



movlw 0x0A               ; cargo W con 10, para transferirlo 

    movwf Digito10



BTFSSPORTA,0; Testeamos si esta a 1 logico.-

GOTOTESTEO; No, seguimos testeando.-



CALLDemora_20ms; Eliminamos Efecto rebote



BTFSSPORTA,0; Testeamos nuevamente.-

GOTOIDENTIFICAR;RUT1





btfssPORTA,1; Testeamos si esta a 1 logico.-

GOTO RD_LED

GOTO TESTEO



IDENTIFICAR

BTFSSLED;REVISO EN QUE ESTADO ESTA EL LED

GOTOE_LED;SI ESTA EN 0 VOY A LA SUBRUTINA PARA ENCENDERLO

GOTOA_LED;SI ESTA EN 1 VOY A LA SUBRUTINA PARA APAGARLO

GOTOTESTEO;Testeamos nuevamente.



E_LED



MOVFDigito,W



SUBWF Digito10,0               ; realizo la resta 10-Digito

    btfsc STATUS,Z           ; si W=11, entonces Z=1  

    goto DANO               ; Cambio el numero mostrado



BSFLED



INCFDigito,1



CALLGrabaEprom



btfscPORTA,0; Esperamos a que se suelte el pulsador -**-

goto$-1; No, PCL - 1, --> btfssPORTA,Pulsador.-

callDemora_20ms; Eliminamos efecto rebote.-

btfscPORTA,0; Testeamos nuevamente.-

goto$-4



GOTOTESTEO



A_LED

BCFLED



btfscPORTA,0; Esperamos a que se suelte el pulsador -**-

goto$-1; No, PCL - 1, --> btfssPORTA,Pulsador.-

callDemora_20ms; Eliminamos efecto rebote.-

btfscPORTA,0; Testeamos nuevamente.-

goto$-4



GOTOTESTEO



DANO

BCFLED

BTFSSPORTA,1

GOTORD_LED

GOTODANO





RD_LED

movlw 0x00               ; cargo W con 10, para transferirlo 

    movwf Digito

CALLGrabaEprom

btfscPORTA,1; Esperamos a que se suelte el pulsador -**-

goto$-1; No, PCL - 1, --> btfssPORTA,Pulsador.-

callDemora_20ms; Eliminamos efecto rebote.-

btfscPORTA,1; Testeamos nuevamente.-

goto$-4; No, Falsa alarma, volvemos a testear a que se suelte (**).-

GOTO TESTEO







;******************************************************************************

;**********************************  EPROM   **********************************

;******************************************************************************

GrabaEprom   

            MOVLW        0x00   ; Direccion de la eprom a grabar

            MOVWF        Addr_EE

            MOVFW        Digito   ; dato a enviar

            MOVWF        Data_EE

            CALL         GRABAR_EEPROM



            return



LeeEprom   

            MOVLW        0x00         ; Direccion que deseo leer

            MOVWF        Addr_EE    

            CALL         LEER_EEPROM

            MOVFW        Data_EE       ;el dato obtenido de la eeprom

            MOVWF        Digito      ;lo pasa a este registro 

            return



;-------------------------------------------------------------------------------------------

; Graba en la memoria EEPROM, verificando la grabación exitosa. En caso de error en la 

; grabación, vuelve a intentarlo. 

; 

;        In:         Addr_EE (Reg)        -> Dirección de la EEPROM donde grabar

;        In:                Data_EE (Reg)        -> Dato a grabar

;

; Nota: - El banco de salida es el 0.

;                - Modificar según se utilicen Interrupciones o no.

;

GRABAR_EEPROM        

                        BANKSEL Addr_EE

                        MOVF        Addr_EE,W        ; Mueve el valor del "Addr_EE" a "W"

                        Banco1

                        MOVWF        EEADR                ; Mueve el valor de "W" al registro "EEADR"

                        BANKSEL Data_EE

                        MOVF        Data_EE,W        ; Mueve el valor del "Data_EE" a "W"

                        Banco1

                        MOVWF        EEDATA                ; Mueve el valor de "W" al registro "EEDATA"

                        BSF                EECON1,WREN        ; Habilita el BIT de escritura en la EEPROM (WREN)

;-------------------------------------------------------------------------------------------;

                         BCF                INTCON, GIE        ; Desabilita las interrupciones

                        MOVLW        0x55                ; Secuencia obligatoria

                        MOVWF        EECON2                ; para activar la grabación

                        MOVLW        0xAA                ; de la memoria 

                        MOVWF        EECON2                ; EEPROM

                        BSF                EECON1,WR        ; Inicia el ciclo de escritura Bit WR

;-------------------------------------------------------------------------------------------;

 ;                        BSF                INTCON, GIE        ; Habilita las interrupciones

                        Banco0

GRABAR_EEPROM_ESPERAR clrwdt

                        BTFSS        PIR1,EEIF        ; Lee ek EEIF y salta una instrucción si el valor es 1

                        GOTO        GRABAR_EEPROM_ESPERAR  ; Espera de grabación de la EEPROM

                        BCF                PIR1,EEIF        ; Limpia el flag EEIF

                        Banco1

                        BCF                EECON1,WREN        ; Deshabilita el Bit de escritura de la EEPROM (WREN)

                        BANKSEL        Data_EE

GRABAR_EEPROM_VERIFICACION

                        MOVFW        Data_EE                        ; Coloca el valor leido en W

                        Banco1

                        BSF         EECON1, RD                ; Leer la EEPROM

                        SUBWF        EEDATA, W                ; Compara el valor leido con el grabado

                        BTFSS        STATUS,Z                ; Si son iguales, salta una instrucción

                        GOTO        GRABAR_EEPROM        ; Si no son iguales, comienza de nuevo la rutina

                        Banco0

                        RETURN

; Fin Rutina: GRABAR_EEPROM ----------------------------------------------------------------





;-------------------------------------------------------------------------------------------

; Lee la memoria EEPROM

;        In:         Addr_EE (Reg)        -> Dirección de la EEPROM donde leer

;        Out:        Data_EE (Reg)        -> Dato leido

;                

LEER_EEPROM

                        BANKSEL     Addr_EE     ;lo situa automaticamente en el banco correspondiente

                        MOVFW       Addr_EE         ; Carga la dirección en W

                        Banco1

                        MOVWF       EEADR                ; Coloca la dirección en EEADR

                        BSF         EECON1, RD        ; Leer la EEPROM

                        MOVF        EEDATA, W        ; Coloca en W el contenido de la EEPROM

                        BANKSEL Data_EE

                        MOVWF       Data_EE                ; Coloca en Data_EE el contenido de W

                        Banco0

                        RETURN

Demora_20ms

movlw0xFF

movwfContador1; Iniciamos contador1.-

Repeticion1

movlw0x19; 

movwfContador2; Iniciamos contador2

Repeticion2

decfszContador2,1; Decrementa Contador2 y si es 0 sale.-

gotoRepeticion2; Si no es 0 repetimos ciclo.-

decfszContador1,1; Decrementa Contador1.-

gotoRepeticion1; Si no es cero repetimos ciclo.-

return; Regresa de la subrutina.-



END

Ya logré que funcionara :D el problema era la línea que le agregué, DT "OBSOLESENCIA PROGRAMADA" eliminé esa línea y listo funcionó!! :D gracias por su ayuda.
Quizás suba el archivo para compartirlo, de pronto a alguien le interese. :cool:
 
Última edición por un moderador:
Hola:

Donde pone DT "OBSOLESENCIA PROGRAMADA" te faltó poner esto:

, 0x00.

El resultado final quedaría así:

DT "OBSOLESENCIA PROGRAMADA", 0x00

Comprueba haber, ejejjeeje. Por supuesto, nos cuenta como te ha ido si te funciona como digo o no.

Un saludo.
 
Hola:

Donde pone DT "OBSOLESENCIA PROGRAMADA" te faltó poner esto:

, 0x00.

El resultado final quedaría así:

DT "OBSOLESENCIA PROGRAMADA", 0x00

Comprueba haber, ejejjeeje. Por supuesto, nos cuenta como te ha ido si te funciona como digo o no.

Un saludo.

¿Y ese 0x00 para qué sirve o que indica?
 
Última edición por un moderador:
Hola... bueno ya acabé el proyecto sobre la obsolescencia programada lo acabe...

Le agregue en el puerto B, 4 LEDs pra que muestren en binario el valor almacenado en la memoria EEPROM...

Adjunto todos los archivos de este proyecto, incluido el .ASM, .HEX, y el archivo con la simulacion en proteus...

Cualquier duda me comentan :cool:

Gracias a todos los que me colaboraron en la elaboracio y corrección de este circuito...
 

Adjuntos

  • Obsolesencia Programada.rar
    44.8 KB · Visitas: 17
Última edición:
Atrás
Arriba