Autor Tema: Como haceil para leer interruptores?  (Leído 12811 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #15 en: 24 de Febrero de 2011, 12:18:07 »
 No importa que no dispongas de un teclado matricial, se puede armar tranquilamente con teclas sueltas.
  Por otro lado se puede usar la interrupción de alguno de los timers para que sea tu base de tiempo para el refresco de los leds.

  Te muestro un ejemplo de como armar un teclado matricial con simples switch. Los pines Col x irían a salidas del pic y los pines Fila x irían a entradas que generen interrupción (RB4..RB7), entonces cuando se presiones alguna tecla se une el puerto de salida con el de entrada y genera interrupción.
  Incluso para tu caso que necesitas 9 pulsadores te alcanza con sólo 6 pines.

!! que locura!
vale, entiendo que es, desde luego, una muy buena solucion: 6 pines y 3 de ellso con interrupcion, se puede hacer si problema
pero no entiendo uan cosa:
cualquier boton de la primera linea va a activar una interrupcion del pin conectado a la priemra linea.... pero como voy a saber que boton ha sido?
gracias (me ayudais muchisimo :))

modifico:
es asi como se hace?
"interrupcion de la primera linea activada"
dentor de la interrupcion "una por una quito la tension de las columnas, caundo el pin 'linea 1' deje de recibir corriente es que he quitado la columna del boton apagado" ??
« Última modificación: 24 de Febrero de 2011, 12:24:38 por excalibur1491 »

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Como haceil para leer interruptores?
« Respuesta #16 en: 24 de Febrero de 2011, 12:51:33 »
Hola Excalibur1491:
       en la página del amigo RedPic podrás ver un ejemplo de la librería de teclado matricial.

http://picmania.garcia-cuervo.net/picc.php#KBDLIB


y aquí tienes otro ejemplo del amigo Sucky.

http://www.todopic.com.ar/foros/index.php?topic=27167.0
           
          Espero te ayuden a aclarar las cosas.
                               Saludos.
                                    Jukinch
"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #17 en: 24 de Febrero de 2011, 15:19:14 »
gracias jukinch ;)

ahora estoy asi:
dentro de mi rpograma grande llamo a print que es durante la unica que quiero que pueda haber interrupciones (enciende unos diodos mientras espera a que la persona pulse un interruptor)
Código: [Seleccionar]
void print(char* T)                        
{
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
output_high(PIN_B0);
output_high(PIN_B1);
output_high(PIN_B2);
output_high(PIN_A0);
  while(j==0)
  {
      //Enciendo unas leds segun una secuencia: funciona bien
  }
disable_interrupts(GLOBAL);
disable_interrupts(INT_RB);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_A0);
j=0;
}

ahora la interrupcion es esta:
Código: [Seleccionar]
#INT_RB //teclado
void teclado(char* T, int* movmntsO, int* M)
{
   int i=4;
   int linea=0;
   int columna=0;
   int mov=0;
   for (i=4;i<7;i++)   //Chequeo que linea ha sido pulsada (rb4, rb5 o rb6)
   {
     if (bit_test(port_b,i)==1)
     {linea=i-3;}  //las lineas se llaman 1 2 o 3... asi que corrijo i
   }
   i=0;
   for(i=0;i<3;i++)
   {
      output_low(31752+i);   // pone a 0 la columna i (el PIN_B0 esta definido en el header como 31752, asi q uso directamente el numero)
      if (bit_test(port_b,linea+3)==0)   //la linea ya no recibe corriente (corrijo.. si linea=1 quiero mirar el rb4, asi que linea+3
      {columna=i;} //
   }
  
   if (linea==1)
   {mov=columna;}                                  //mi cuadro T es asi: {0 ,1 ,2
   if (linae==2)                                                                      3, 4, 5,
   {mov=columna+3;}                                                           6, 7, 8}
   if (linea==2)
   {mov=columna+6;}
   movmntsO[*M]=mov;      //  esto funciona bien ;)              
   T[mov]='O';  
   *M=*M + 1;  
  
   j=1;  //para para la funcion print
   clear_interrupt(INT_RB);
}


y al principio d ela funcion main:
Código: [Seleccionar]
     
port_b=0x00;
  
set_tris_b(0b01110000);  
y lo que sucede este me hace bien la secuencia de leds cuando entra por primera vez en print(T) pero en cuandot pulso un interruptor, se paga todo y buenas noches..... No sé que fallo hay,
os paso el circuito tb:

muchas gracias :)
« Última modificación: 24 de Febrero de 2011, 19:12:04 por excalibur1491 »

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Como haceil para leer interruptores?
« Respuesta #18 en: 24 de Febrero de 2011, 19:00:22 »
excalibur1491:
                   Podés subir el código completo y el dsn así chequeo el funcionamiento.
                                                  Saludos.
                                                         Jukinch
"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #19 en: 24 de Febrero de 2011, 20:32:46 »
excalibur1491:
                   Podés subir el código completo y el dsn así chequeo el funcionamiento.
                                                  Saludos.
                                                         Jukinch

como es para un trabajo, prefiero que no esté el codigo completo por internet, asi que pongo la parte que falla (he borrao todo dejando solo esta aprte, y no funciona como es debido, asi q...)
explico:
en la funcion main tenemos un cuadro T (cuadro del juego tic-tac-toe) , un cuadro momntsO que contiene las casilals de T en las que está puesto 'O' , un contador movimientos que cuenta cuantos movimientos de O ha habido y su puntero M.
aqui, para abrebiar, he puesto el caudro T conteniendo ya 3 X en las casillas 1 4 y 6 de T (asi que se encienden, parpadeando, las leds correpsondientes, eso funciona OK)
ahora, mientras se esta en la funcion print (de la cual no se sale a menos que se declare una interrupcion), al pulsar un boton se detecta a que linea y a q columna pertenece el boton pulsado y se enceinde el diodo correspondiente (porque se ha colocado un 'O' en la casilla de T correspondiente) PERO NO FUNCIONA.

adjunto codigo y circuito

relamente, muchas gracias ;)

P.D.: una curiosidad: si añado output_high(31768+linea+columna); en la funcion telcado justo antes de la tanda de if's al final, depues del 2º for, enciende el diodo correcto pero me enciende, ademas el diodo conectado a D2 (siempre el mismo)...
« Última modificación: 25 de Febrero de 2011, 10:02:26 por excalibur1491 »

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Como haceil para leer interruptores?
« Respuesta #20 en: 24 de Febrero de 2011, 20:56:30 »
excalibur1491:
           Subí sólo la parte del header en donde definís los pines.
En los comentarios hacés referencia a que el PIN_B0 esta definido en el header como 31752 y si no me equivoco me parece que luego lo utilizas como si hicieras referencia a  todo el puerto b completo?
Por las dudas te aclaro que las funciones output_high(PIN); o output_low(PIN); sólo controlan un pin del microcontrolador,
Si quieres controlar todo el puertob entero, usá la función output_b(DATO);
             Jukinch       
"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #21 en: 25 de Febrero de 2011, 06:31:42 »
excalibur1491:
           Subí sólo la parte del header en donde definís los pines.
En los comentarios hacés referencia a que el PIN_B0 esta definido en el header como 31752 y si no me equivoco me parece que luego lo utilizas como si hicieras referencia a  todo el puerto b completo?
Por las dudas te aclaro que las funciones output_high(PIN); o output_low(PIN); sólo controlan un pin del microcontrolador,
Si quieres controlar todo el puertob entero, usá la función output_b(DATO);
             Jukinch       

mmm.. no.. el pin B0 es bien el 31752.. y yo lo que hago en m segundo bucle for es: apago una columna, miro si sigue habiendo tension en la linea (si no la hay, esq he apagao la columna del interruptor pulsado), vuelvo a encenderla y cequeo asi la segunda columna....etc..

los pines estas definidos asi:

#define PIN_A0  31744
#define PIN_A1  31745
#define PIN_A2  31746
#define PIN_A3  31747
#define PIN_A4  31748
#define PIN_A5  31749
#define PIN_A6  31750

#define PIN_B0  31752
#define PIN_B1  31753
#define PIN_B2  31754
#define PIN_B3  31755
#define PIN_B4  31756
#define PIN_B5  31757
#define PIN_B6  31758
#define PIN_B7  31759

#define PIN_C0  31760
#define PIN_C1  31761
#define PIN_C2  31762
#define PIN_C4  31764
#define PIN_C5  31765
#define PIN_C6  31766
#define PIN_C7  31767

#define PIN_D0  31768
#define PIN_D1  31769
#define PIN_D2  31770
#define PIN_D3  31771
#define PIN_D4  31772
#define PIN_D5  31773
#define PIN_D6  31774
#define PIN_D7  31775

#define PIN_E0  31776
#define PIN_E1  31777
#define PIN_E2  31778
#define PIN_E3  31779
#define PIN_E7  31783


gracias ;)

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #22 en: 25 de Febrero de 2011, 06:43:00 »
uy, esto se pone siniestro....
si en la interrupcion borro todo y dejo solo T[5]='O' .. T[5] no recibe O... y se apaga todo....
esq acaso el T de la interrupcion no es el mismo que en todos laos??

gracias ;)
« Última modificación: 25 de Febrero de 2011, 10:01:58 por excalibur1491 »

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #23 en: 25 de Febrero de 2011, 10:07:35 »
BUENO! Ahora sí funciona bien!
he hecho lo siguiente:
crear 2 variables globales columna y linea. la funcion de interrupcion no tiene parametros y solo se ocupa de determinar la linea y la columna, y dentro de print he hehco tod lo que tiene que ver con el cuadro T etc.... asi la de la interrupcion no tiene nada que ahcer mas que cambair el valor de 2 variables globales


sin embrgo: la interrupcion es tan lenta que a vece no llega a leer todo antes de quitar el dedo del pulsador.. asiq ue he quitado todo lo que era outpout_low en el segundo for, apra que vaya mas rapido y ahora parece funcionar bien.
para evitar rebotes he tenido que poner un delay_ms(100) al final de la funcion ....

ahora tnego una duda: yo todo esto lo hacia para poder hacer que mi funcion print, en vez de encender todas las leds a al vez, encienda una por una muy rapido.... pero como esto lo hago con ifs, desde que enciende la de arriba a la izquierda ahsta que enciende la de abajo a la derecha, para un tiempo sin que haya nada encendido....
algun consejo apra optimizar esto? :)

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Como haceil para leer interruptores?
« Respuesta #24 en: 25 de Febrero de 2011, 10:59:33 »
excalibur1491:
               Con relación al tema del array vi el código esta mañana y veo que lo has resuelto solo y era por el ámbito del array T[] el cual estaba declarado dentro de main y no como global como las otras variables que usabas.
         Con respecto a la optimización te sugiero que dentro de la interrupción hagas lo menos posible. Tan sólo cambiar de estado banderas para luego consultarlas en el programa principal para que no se haga un cuello de botella en el código e implementes un antirebote con un algoritmo que no espere un tiempo X. (como es el delay_ms(100))
         Para ello verifica 10 veces seguidas si una variable de tipo bool como ser botonPulsado sea verdadera las 10 veces seguidas en que la consultaste. Con eso detectarás que el botón se haya pulsado de verdad y no que sea ruido.-
         Si no llega a ser verdadera en una de las 10 veces en que consultaste, que descarte la pulsación y vuelva a ingresar al bucle en donde comprobás si se pulsó el botón. Con esto eliminarás el ruido de la pulsación de los botones y serán menores las esperas.
         Y tambíen usaría un cristal que me de el mayor clock para la velocidad de trabajo del micro.
                 Saludos.
                       Jukinch.
"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #25 en: 25 de Febrero de 2011, 11:09:39 »
excalibur1491:
               Con relación al tema del array vi el código esta mañana y veo que lo has resuelto solo y era por el ámbito del array T[] el cual estaba declarado dentro de main y no como global como las otras variables que usabas.
         Con respecto a la optimización te sugiero que dentro de la interrupción hagas lo menos posible. Tan sólo cambiar de estado banderas para luego consultarlas en el programa principal para que no se haga un cuello de botella en el código e implementes un antirebote con un algoritmo que no espere un tiempo X. (como es el delay_ms(100))
         Para ello verifica 10 veces seguidas si una variable de tipo bool como ser botonPulsado sea verdadera las 10 veces seguidas en que la consultaste. Con eso detectarás que el botón se haya pulsado de verdad y no que sea ruido.-
         Si no llega a ser verdadera en una de las 10 veces en que consultaste, que descarte la pulsación y vuelva a ingresar al bucle en donde comprobás si se pulsó el botón. Con esto eliminarás el ruido de la pulsación de los botones y serán menores las esperas.
         Y tambíen usaría un cristal que me de el mayor clock para la velocidad de trabajo del micro.
                 Saludos.
                       Jukinch.

pregunta esencial: que son las flags, y como se usan? xD graciaas

con respecto al antirrebotes... no enteindo que tiene que hacer botonPulsado.... vale 1 si lo pulso, mientras valga 1 (10 veces en un while que englobe toda la funcion de teclado) hago lo que hay dentro de la funcion del teclado?? no he entendido muy bien....

gracias por toda la ayuda ;)

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Como haceil para leer interruptores?
« Respuesta #26 en: 25 de Febrero de 2011, 12:12:55 »
Excalibur1491:
TEMA INTERRUPCIONES:
                Para que una interrupción cumpla con su cometido el código que pongas dentro de la misma tiene que ser lo más corto que puedas y que dure el menor tiempo posible.
               Para ello se utilizan variables que se las llama normalmente Flags o banderas (para consultar su estado luego dentro del código princial). Si usás un código muy extenso dentro de la interrupción corrés el peligro de que por tardar mucho tiempo ocurra el evento que estás controlando nuevamente y además te quite tiempo para lo que estás haciendo en el código principal. No se si me explico.

Por ejemplo, te paso el pseudocódigo:

INTERRUPCION:
             alarmaEncendida=1;


FIN INTERRUPCIÓN



DENTRO DE MAIN:
while(1)
   { // BUCLE PRINCIPAL
                  if (alarmaEncendida==1)
                                            {
                                              // hago lo que me interesa que se actualice rápido
                                              alarmaEncendida  = 0; // Asigno a la variable alarmaEncendida el valor de cero (0) para que no vuelva
                                                                                  // a este sector del código excepto si se ha producido la interrupción.
                                             }
                 else
                         {
                          // hago otra cosa
                          }                        
} // FINAL DE BUCLE PRINCIPAL



Aquí tienes algunos ejemplos de uso de banderas.
http://todopic.mforos.com/46840/5068985-ejemplos-para-pic16f877-con-ccs/


TEMA ANTIRREBOTE:

            normalmente se usa una espera de x milisegundos para evitar que una pulsación mecánica se interprete digitalmente como varias pulsaciones por los motivos que ya conoces.
            Pero eso no es lo óptimo. ¿Por que esperar X tiempo?
            Se puede comprobar en menos tiempo que X.
Para ello debes crear un algoritmo que verifica si el botón se pulsó, y además se mantuvo pulsado durante x iteraciones.

Un ejemplo a continuación:

do   {

     if (input(PIN_B0) ) // controla si el botón se pulsó
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;

 }while(arranca<=100);   // el valor de 100 lo podés variar en más o en menos para afinarlo a tu necesidad.


Es poco probable que tengas un ruido que dure 100 iteraciones seguidas con el estado alto de RB0.
Y así el tiempo de este algoritmo es mucho menor que esperar 1 milisegundo. Se entiende?
Sinó avisá y te amplío el concepto.
               Saludos.
                         Jukinch

"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Como haceil para leer interruptores?
« Respuesta #27 en: 25 de Febrero de 2011, 12:27:32 »
  Es muy interesante la idea de jukinch para evitar los revotes.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado excalibur1491

  • PIC10
  • *
  • Mensajes: 44
Re: Como haceil para leer interruptores?
« Respuesta #28 en: 25 de Febrero de 2011, 12:53:06 »
jukinch, genial tu explicacion de las bandera, ;) lo entendi perfecto , mil gracias ;)


TEMA ANTIRREBOTE:

            normalmente se usa una espera de x milisegundos para evitar que una pulsación mecánica se interprete digitalmente como varias pulsaciones por los motivos que ya conoces.
            Pero eso no es lo óptimo. ¿Por que esperar X tiempo?
            Se puede comprobar en menos tiempo que X.
Para ello debes crear un algoritmo que verifica si el botón se pulsó, y además se mantuvo pulsado durante x iteraciones.

Un ejemplo a continuación:

do   {

     if (input(PIN_B0) ) // controla si el botón se pulsó
         arranca=arranca+1;
      ELSE
          IF (ARRANCA>1)
            arranca=arranca-1;

 }while(arranca<=100);   // el valor de 100 lo podés variar en más o en menos para afinarlo a tu necesidad.


Es poco probable que tengas un ruido que dure 100 iteraciones seguidas con el estado alto de RB0.
Y así el tiempo de este algoritmo es mucho menor que esperar 1 milisegundo. Se entiende?
mm, no, no se entiende, xD
si arrnca==0, y pulsas B0, arranca==1 y el bucle vuelve a empezar.. si sigues pulsando, arranca==2  y luego arranca==1 y asi hasta el infinito... y arranca no será >100 jamas y estaras en el bucle apra siempre.. no??
y este antirrebotes, donde se pone? en la interrupcion o en la funcion principal??

otra vez: gracias ;)

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Como haceil para leer interruptores?
« Respuesta #29 en: 25 de Febrero de 2011, 13:00:37 »
  La variable arranca se incrementa mientras el botón esté presionado. Se decrementa si el botón es soltado.

  Hay que tener en cuenta que un reboto sería algo así como presionar y soltar varias veces el botón.

  El loop sirve para leer el puerto varias veces seguidas, hasta que la variable arranca llegue hasta 100.


  Ahora a mí me están entrando algunas dudas..... pero no quiero complicarte excalibur1491, así que luego consultaré
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything