# Pic para encendido de cuartos y faros con botón pulsador.



## Daferu (Ene 5, 2010)

Me encuentro realizando un proyecto para controlar el encendido y apagado de las luces de mi camioneta, todo empezó cuando se descompuso la llave del encendido de luces (una palanquita que esta por el volante), entonces se me ocurrió emular la misma función de esa palanca con un pulsador y empecé a diseñar circuitos que me ayudaran con esa tarea, primero probé con un contador con Flip Flops JK que lo único que hacía era una secuencia de dos bits (0,1,3,1,0) en donde el estado cero era igual a los cuartos y las luces apagadas, con el uno solo los cuarto prendían y con el tres los cuartos permanecían prendidos y además se encendían los faros, y de regreso hasta quedar apagados los faros y los cuartos, cada cambio de estado era hecho mediante un pulso proveniente de un circuito debounce, el problema de este sistema era que solo en caminos en donde no hubiera baches funcionaba correctamente, pero al pasar a terracería las vibraciones provocadas por los baches ocasionaban un cambio de estado en el contador provocando que los faros se apagaran.

  Ahora estoy tratando de controlar las luces con un pic ya que considero que será menos sensible a las vibraciones por el hecho de que el control radica en un solo IC, no sé si estoy en lo cierto??. Para programar el pic utilizo lenguaje C y como compilador el PCWHD, cabe mencionar que este es el primer proyecto que realizo con un pic y el compilador pcw. Bueno el punto es que ya logre tener avances en la programación y logre hacer CASI la misma secuencia de (0,1,3,1,0) cada vez que el pic recibe un pulso en el bit 0 del puerto a y digo CASI porque no he logrado que se regrese al estado cero, el programa ya lo repace y no encuentro el error, cuando lo simulo en proteus solo funciona si el PB se queda presionado, pero si trato solo de mandar pulso logro que la secuencia sea 0,1,3,1 y el siguiente estado toma un valor al azar y no es cero. no se si me puedan ayudar con esto??, tal vez la solución está en implementar un debounce en el programa?? O que me siguieren.
  Adjunto el diagrama y el programa.
  Saludos.   


```
#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPUT,NOPROTECT
#byte port_a=0x05
#byte port_b=0x06

int contador;

void main()
{       
set_tris_a(0x01);
set_tris_b(0xfc);


port_b=0;
contador=1;

while (true)
Inicio:

revisar:
{
if (port_a==1)
{
delay_ms(1000);
port_b=contador;

contador=contador+2;
revisar_1:
if (port_a==1)
{
delay_ms(1000);
port_b=contador;
contador=contador-2;
revisar_2:
if (port_a==1)
{
delay_ms(1000);
port_b=contador;
revisar_3:
if (port_a==1)
{
delay_ms(1000);
port_b=0;
contador=1;
delay_ms (100);
goto Inicio;
}
else if (port_a==0)
goto revisar_3;
}
else if (port_a==0)
goto revisar_2;
}
else if (port_a==0)
goto revisar_1;
}
else if (port_a==0)
goto revisar;
}
}
```


----------



## cosmefulanito04 (Ene 5, 2010)

Te doy un consejo, trata de no mezclar C con goto, de hecho goto es mala palabra a lo que programacion se refiere (salvo ASM que es el nivel mas bajo de programacion).

¿Motivo principal? si bien en un proyecto relativamente simple el problema no es tan grave, mientras mayor sea el mismo, mejor sera que tu codigo sea entendible y ordenado, si tenes goto por todos lados, se vuelve un plato de fideos el codigo, y te empezas a volver loco. Por otro lado, mientra mas evites esos saltos bruscos de memoria, mas rapido correra tu programa.

Pensa que C es un lenguaje estructurado, es decir que tu codigo tiene que tener una entrada y una salida (en caso de haberla), y usando if/while/for, y sobre todo funciones, te deberia alcanzar para realizar el programa. Esta es la gran ventaja que tiene C respecto al ASM, tener codigo mucho mas ordenado y facil de entender.


----------



## Daferu (Ene 5, 2010)

Ok, entonces optimizare el código, será acaso que por esos saltos bruscos que mencionas tenga las salidas erróneas en el pic??


----------



## cosmefulanito04 (Ene 5, 2010)

No, si los saltos están bien hechos, el programa debería funcionar sin inconvenientes.

Igual, asi y todo vas a seguir teniendo problemas con los baches, porque ahi se produce lo que se llama rebote, una posible solución seria agregándole un filtro pasa bajo con un tao importante, tal que no moleste. Si todavía tenes el circuito que diseñaste anteriormente, proba poniéndole ese filtro que te dije. 

La idea seria un antirrebote, ver adjunto.

El circuito tiene un tao de 220mSeg durante la carga y 330mSeg (que puede variar con la carga que le metas) durante la descarga, osea lo mate, y la idea es que haya 220 mSeg antes de llegar al nivel lógico 1 y 320 mSeg hasta llegar al 0 lógico nuevamente, osea 1/2 seg para completar el ciclo completo, estos valores anda modificandolos hasta llegar a un valor en el que no te resulte incomodo la espera y que no se produzca el rebote que mencionas a la hora de los baches.

Con el Pic, podrías hacer ese filtro, pero por software.


----------



## jesus_lomor (Ene 5, 2010)

Por los baches?.. me suena a una mala conexion del pulsador, no se si este equivocado... en que lo tienes montado, proto?... si acaso, intenta con circuito impreso o tableta perforada, podria solucionar el problema...


----------



## Daferu (Ene 5, 2010)

El circuito está montado en una tablilla perforada y el push bottom está en el tablero a unos 40 cm de donde está el circuito, no sé si esa distancia afecte?? De todas formas volveré a hacer el circuito pero ahora en circuito impreso y con el filtro pasa bajas que dice cosmefulanito04, aunque también intentare implementarlo en software, alguna sugerencia para este punto??.
   Saludos.


----------



## cosmefulanito04 (Ene 5, 2010)

Mira yo nunca use un Pic, siempre trabaje con Arm u 8051, pero aca te dejo una maquina de estado para que te sea facil entender el problema y arreglar el codigo para que funcione en Pic, ademas se ajusta perfectamente a lo que queres:



Codigo en C:


```
....
unsigned char estado=0;

void main(void)
{
	set_tris_a(0x00);  // Port A = 0 y espero a que se presione el pulsador 
	set_tris_b(0xfc);  // Empiezo la secuencia con 00

	while(1)
	{
		while(!(port_a&0x001));	// Espero hasta que el Puerto a.0 se active 
		switch(estado)
		{
			case 0: {
					set_tris_b(0xfc);
                                        estado=1;
					break;
					}
			case 1: {
					set_tris_b(0xfd);
                                        estado=2;
					break;
					}
			case 2: {
                                        set_tris_b(0xff);
                                        estado=3;
					break;
					}
			case 3: {
					set_tris_b(0xfd);
                                        estado=0;
					break;
					}

		}

	}

}
```

Otra cosa, en vez de usar un delay para hacer polling, tal vez te conviene usar la interrupcion del puerto B0. Y un seg de espera es mucho tiempo, convendria baja a 1mSeg.


----------



## Meta (Ene 6, 2010)

El anirebote lo cosigues mediante hardware con puertas NAND como esta...






O mediante retardos que las puedes calcular aquí.

http://www.golovchenko.org/cgi-bin/delay

El ciruito que tienes, puedes meterle uno más pequeño y sencillo ahorrando más componentes como PIC de 8 pines que te pueden valer es;

12F508
12F509
12F629
12F675

Saludo.


----------



## cosmefulanito04 (Ene 6, 2010)

Se me paso ponerle los break al switch . De paso, te dejo una modificacion en el polling.


----------



## Daferu (Ene 7, 2010)

Si de hecho estaba pensando utilizar un pic de la gama baja pero el 16f84 fue el único que tenia disponible en el momento en que empecé con esto, de todos modos ya me puse a investigar y encontré que en las tiendas de electrónica en donde vivo no están tan caros, haber si la siguiente semana me consigo. 

Cosmefulanito04 no se si puedas explicarme un poco más acerca de la instrucción que utilizas en el código que posteaste, la de switch (estado) porque no supe que es lo que hace el programa con eso, ya estuve buscando y encontré que se usa cuando se tiene un menú o algo similar, no sé si puedas aclararme la duda, ha otra cosa la instrucción de set_tris que no se utiliza solo para definir cómo quieres configurados los pines del pic ya sea como entradas o salidas o me equivoco??  

  Saludos.


----------



## Meta (Ene 7, 2010)

Tiene un Led directo al PIC, el otro a un inversor. No uses inversores, mete el segundo led al PIC también en otro pin. Ahorras integrados o componentes innecesario.


----------



## cosmefulanito04 (Ene 7, 2010)

Ves ahi se pone en evidencia que nunca use un Pic , por eso te hice esa maquina de estado.

Entonces, lo que deberias hacer es modificar el codigo para que antes de entrar al While(1), Pb.0 y Pb.1 funcionen como salida y Pa.0 como entrada.

Luego dentro de c/case de los switch tenes que cambiar set_tris_b(....); por el comando que se use para modificar los puertos, en el 8051 seria P2=0xff (pongo en 1 todo el puerto 2). Entonces en el case 0 tu modificacion quedaria asi:


```
...
                           case 0: {
					// Setear 0xfc al puerto B
                                        estado=1;
					break;
					}

...
```

Lo mismo haces con el resto de los casos. De esta forma conseguis esta secuencia:

{00,01,11,01} -> y repite todo de nuevo.

El Switch es una opcion diriamos un poco mas avanzada que el if, en donde te permitiria elegir multiples caminos en funcion del valor de una variable, en cambio el if solo te permite 2 camino el verdadero o el falso.

Otro codigo alternativo a ese podria ser:


```
...
void main(void)
{
    unsigned char estado[4]={0x00,0x01,0x03,0x01},indice=0;
    
    // <-- Aca Configuro los puertos B como salida y el A como entrada
    while(1)
       {
	   while(!(port_a&0x001)); // Espero a que el puerto A cambie de estado
	   puerto_B=estado[indice]; // <-- Aca ingreso el nuevo valor del puerto B, 
	   indice++;
	   if(indice==4)
	   	  indice=0;	
       }
}
```

Como ves, las alternativas son varias, ambos codigos deberian funcionar bien, la unica diferencia es que el 1ero es recontra estructurado, pero facil de entender una vez realizado el diagrama de estados, en cambio el 2do es mas intuitivo.


----------



## Daferu (Ene 30, 2010)

Hola, gracias por su ayuda, me di cuenta que aun me falta mucho que aprender de los microcontroladores por eso me voy a inscribir en un curso que están dando acá en donde vivo y seguiré haciendo prácticas sencillas para obtener experiencia. Meta visite tu blog y encontré ejemplos muy buenos con el 16f84 creo que podre modificar alguno para hacer este proyecto  ya que el código se parece un poco al que postea cosmefulanito04.
  Saludos.


----------



## alarmero (May 12, 2010)

Hola!
Espero que este comentario mio no llegue muy tarde...
Estaba viendo que comentas que cuando andas por camino liso, no hay problema; pero cuando andas por camino empedrado o con baches, cambia de estado el circuito contador y entonces se apagan las luces.
Yo creo que no tiene nada que ver el hecho de que el circuito de entrada no tenga antirrebote, porque en el momento de agarrar los baches, no se están pulsando los botones.
Entiendo que el circuito antirrebotes impide un funcionamiento errático al pulsar los botones y no es el caso.
Yo creo que el problema puede estar en que el conexionado eléctrico del vehículo no debe estar en buenas condiciones. Por ejemplo: falsos contactos en los cables de masa, falta de masa en el capot, conexiones oxidadas o sulfatadas, etc.
Si esto estuviera pasando, al hacer vibrar el vehículo, se producen falsos contactos que generan ruido eléctrico y puede afectar a los circuitos digitales ya que estos son muy sensibles pero sobre todo muy rápidos.
Tal vez lo soluciones con un simple capacitor en las entradas de estos circuitos.

Saludos!!!!
Daniel


----------

