Autor Tema: Leer una combinacion  (Leído 2367 veces)

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

Desconectado raul6162

  • PIC10
  • *
  • Mensajes: 19
Leer una combinacion
« en: 10 de Marzo de 2017, 19:01:47 »
Saludos, estoy haciendo una activación por clave, esta se muestra en 4 leds y necesito la ingresen mediante 4 push botons, el problema es que no se como leer la combinación puesto que no mantendrán oprimidos los botones solo pulsados por momentos, si leo todo el puerto me leerá el estado en ese momento, y no recogerá ningún valor. será que almacene los pulsos con un arreglo pero no tengo idea la verdad?
 :( ojala me den una idea.
programo en CCS.
« Última modificación: 10 de Marzo de 2017, 19:20:21 por raul6162 »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5470
    • Electrónica Didacta
Re:Leer una combinacion
« Respuesta #1 en: 11 de Marzo de 2017, 00:35:18 »
con banderas lo resuelves,

creas tantas banderas según las teclas, y cada vez que el usuario presione, se colocas en 1 la bandera correspondiente, luego al final del escaneo, revisas las banderas y sabrás cual tecla es.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Leer una combinacion
« Respuesta #2 en: 11 de Marzo de 2017, 09:03:46 »
Podes leer el puerto y consultar con el valor almacenado anterior, si cambio te preguntas cual fue. Entonces si la persona presiona y mantiene presionado, al ser iguales con el valor guardado no accede.

Desconectado raul6162

  • PIC10
  • *
  • Mensajes: 19
Re:Leer una combinacion
« Respuesta #3 en: 11 de Marzo de 2017, 22:24:16 »
con banderas lo resuelves,

creas tantas banderas según las teclas, y cada vez que el usuario presione, se colocas en 1 la bandera correspondiente, luego al final del escaneo, revisas las banderas y sabrás cual tecla es.
Saludos lo intente por tu meto pero no funciona.
Implemente un for con 5 ciclos de 500 ms, tiempo para ingresar la combinación le he puesto una sencilla de momento "puros unos". solo me enciende los leds espera el segundo y luego me imprime el contador que me confirma es correcta la combinación, y solo imprime el cero pues no lee el for los pulsos. Aquí mi código.

#include <16F873a.h>             
#include <stdlib.h>
#fuses XT, NOWDT
#use delay(clock=4000000)
#use RS232(BAUD=9600,BITS=8,XMIT=PIN_C6,RCV=PIN_C7)
int cont=0,b1=0,b2=0,b3=0,b4=0;

void main (){
      while(true)
      {
      delay_ms(3000);   
      output_high(pin_b0);
      output_high(pin_b1);
      output_high(pin_b2);
      output_high(pin_b3);
      delay_ms(1000);
      for(int i=0;i<5;i++);
      {
      if(input(pin_c0)==1)
      {
      b1=1;
      }
      if(input(pin_c1)==1)
      {
      b2=1;
      }
      if(input(pin_c2)==1)
      {
      b3=1;
      }
      if(input(pin_c3)==1)
      {
      b4=1;
      }
      delay_ms(500);
      }     
      if(b1==1 && b2==1&& b3==1 && b4==1)
      {
      cont=1;
      }
      output_low(pin_b0);
      output_low(pin_b1);
      output_low(pin_b2);
      output_low(pin_b3);
      printf("\fContador:      %u", cont);   
   }
   
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Leer una combinacion
« Respuesta #4 en: 11 de Marzo de 2017, 22:29:51 »
Bueno vamos a hacer una cosa...

Trata de explicar correctamente como deberia funcionar. Yo te propongo que primero hagas algo asi:

Comienzo de Loop Principal.
-- Espero que suelten todos los botones
-- Espero que algun boton se presione, se presiona y guardo el 1er boton
-- Espero que suelten todos los botones
-- Espero que algun boton se presione, se presiona y guardo el 2do boton
-- Espero que suelten todos los botones
-- Espero que algun boton se presione, se presiona y guardo el 3er boton
-- Espero que suelten todos los botones
-- Espero que algun boton se presione, se presiona y guardo el 4to boton

-- Muestro

-- Hago una pausa asi puedo verlo en los leds

Fin del loop principal

Desconectado raul6162

  • PIC10
  • *
  • Mensajes: 19
Re:Leer una combinacion
« Respuesta #5 en: 12 de Marzo de 2017, 00:18:31 »
Básicamente mi problema es leer/escanear en un intervalo de tiempo (digase 3 segundos) las 4 pulsaciones, y luego verificar la combinación sea correcta.
jaja la verdad me estoy resignando a usar el DIP-Switch que ya fija los valores de lectura, me es difícil tratar las pulsaciones. :(

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Leer una combinacion
« Respuesta #6 en: 12 de Marzo de 2017, 00:58:16 »
Es decir que la persona debe poner el codigo de 4 digitos en 3 segundos ?, nuevamente te pido que me expliques como queres que funcione, no que tengas que leer en intervalos (no te pido lo que tenes que hacer para que funcione como queres), sino desde el putno de vista de una persona que lo usa:

Ejemplo:
Pone el codigo de 4 digitos, si pasan 10seg desde la ultima pulsacion se borra todo y comeinza de 0. Si es correcto se acciona un bit de un puerto, si es erroneo se acciona otro bit. Los puertos de entradas son RB0 al RB4. Eso nomas te estoy pidiendo.
« Última modificación: 12 de Marzo de 2017, 01:02:33 por KILLERJC »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5470
    • Electrónica Didacta
Re:Leer una combinacion
« Respuesta #7 en: 12 de Marzo de 2017, 01:25:40 »
con banderas lo resuelves,

creas tantas banderas según las teclas, y cada vez que el usuario presione, se colocas en 1 la bandera correspondiente, luego al final del escaneo, revisas las banderas y sabrás cual tecla es.
Saludos lo intente por tu meto pero no funciona.
Implemente un for con 5 ciclos de 500 ms, tiempo para ingresar la combinación le he puesto una sencilla de momento "puros unos". solo me enciende los leds espera el segundo y luego me imprime el contador que me confirma es correcta la combinación, y solo imprime el cero pues no lee el for los pulsos. Aquí mi código.

#include <16F873a.h>             
#include <stdlib.h>
#fuses XT, NOWDT
#use delay(clock=4000000)
#use RS232(BAUD=9600,BITS=8,XMIT=PIN_C6,RCV=PIN_C7)
int cont=0,b1=0,b2=0,b3=0,b4=0;

void main (){
      while(true)
      {
      delay_ms(3000);   
      output_high(pin_b0);
      output_high(pin_b1);
      output_high(pin_b2);
      output_high(pin_b3);
      delay_ms(1000);
      for(int i=0;i<5;i++);
      {
      if(input(pin_c0)==1)
      {
      b1=1;
      }
      if(input(pin_c1)==1)
      {
      b2=1;
      }
      if(input(pin_c2)==1)
      {
      b3=1;
      }
      if(input(pin_c3)==1)
      {
      b4=1;
      }
      delay_ms(500);
      }     
      if(b1==1 && b2==1&& b3==1 && b4==1)
      {
      cont=1;
      }
      output_low(pin_b0);
      output_low(pin_b1);
      output_low(pin_b2);
      output_low(pin_b3);
      printf("\fContador:      %u", cont);   
   }
   
}

y el retardo antirebotes?

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado raul6162

  • PIC10
  • *
  • Mensajes: 19
Re:Leer una combinacion
« Respuesta #8 en: 12 de Marzo de 2017, 02:18:46 »
Es decir que la persona debe poner el codigo de 4 digitos en 3 segundos ?, nuevamente te pido que me expliques como queres que funcione, no que tengas que leer en intervalos (no te pido lo que tenes que hacer para que funcione como queres), sino desde el putno de vista de una persona que lo usa:

Ejemplo:
Pone el codigo de 4 digitos, si pasan 10seg desde la ultima pulsacion se borra todo y comeinza de 0. Si es correcto se acciona un bit de un puerto, si es erroneo se acciona otro bit. Los puertos de entradas son RB0 al RB4. Eso nomas te estoy pidiendo.
Si he sido ambiguo me disculpo,  como habrán notado soy estudiante y nuevo en pics.
Mi pic mostrará un patrón (combinación de 4 bits) mediante leds (salidas puertob del 0 a 3), luego el usuario ingresará el patrón por push bottons(entradas puertoc del 0 a 3), tendra un tiempo estimado de 3 segundos ( aquí es donde esta mi problema generar una tarea que acepte las pulsaciones para que al término del tiempo (los 3 segundos),  salga del scaneo y compruebe la combinación, si resulta correcta el contador se pone en 1.
« Última modificación: 12 de Marzo de 2017, 10:05:27 por raul6162 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Leer una combinacion
« Respuesta #9 en: 12 de Marzo de 2017, 11:20:30 »
Código: C
  1. int8 patron[4]={0b0001,0b0010,0b0100,0b1000};
  2. int8 i,indice;
  3. int8 valoranterior, valoractual;
  4. itn1 codigocorrecto
  5.  
  6.  
  7. while(1)
  8. {
  9.  
  10.         // Muestro lo que debe introducir
  11.         for( i=0 ; i < sizeof patron; i++)
  12.         {
  13.                 output_c(patron[i]);
  14.                 delay_ms(800);
  15.         }
  16.  
  17.         //Espero que se suelten todos los botones
  18.         //Agregar aca el codigo para eso
  19.  
  20.  
  21.         codigocorrecto = 0;
  22.         valoranterior = 0;
  23.  
  24.         // Procedo a leer los pulsadores por un tiempo de 60 x 50ms = 3000ms
  25.         // Si quisiera auemntar el tiempo, aumentaria el valor que debe alcanzar i, ejemplo
  26.         // si quisiera 6s aumentaria la condicion del for a i < 120 ( 120x50ms = 6000ms )
  27.  
  28.         for( i=0, indice=0; i < 60; i++)
  29.         {
  30.                 // Compruebo primero que lo presionado sea distinto a la anterior pasada del for
  31.                 valoractual = LecturaPort & 0b1111;
  32.                 if (valoractual != valoranterior)
  33.                 {
  34.                         //Si es distinto entra aca, de esa forma yo se que algo cambio desde lo que se presiono antes
  35.                         //Este es el caso en que se presione un boton o muchos o directamente se suelten todos
  36.                         // No debo tomar cuando se suelten todos, asi que pregunto que para entrar posea algo presionado
  37.                         if(valoractual != 0)
  38.                         {
  39.                                 //Aca hay algo presionado, solo me queda confirmar que lo presionado sea lo mismo que mostramos
  40.                                 //Por eso compruebo en orden que se cumpla
  41.                                 if(patron[indice] == valoractual)
  42.                                 {
  43.                                         //Si entro aca quiere decir que el valor que se presiono fue correcto
  44.                                         // Asi que aumento el indice para el proximo valor a presionar
  45.                                         indice++;
  46.                                         // En caso de que se pusieron todos los valores entonces salgo y marco como correcto
  47.                                         if(indice>=sizeof patron)
  48.                                         {
  49.                                                 //Codigo Completo
  50.                                                 codigocorrecto=1;
  51.                                                 break;
  52.                                         }
  53.                                 }
  54.                                 else
  55.                                 {
  56.                                         //Aca se introdujo otro valor no correcto
  57.                                         //Procedo a salir
  58.                                         break;
  59.                                 }
  60.                         }
  61.                 }
  62.                 delay_ms(50);
  63.                 valoranterior = valoractual;
  64.         }
  65.  
  66.         if(codigocorrecto == 1)
  67.         {
  68.                 //Aca lo del codigo correcto
  69.         }
  70.         else
  71.         {
  72.                 //Aca lo del codigo incorrecto
  73.         }
  74.  
  75. }

Personalmente me gustaria mas una solucion con un timer, pero aca tenes una solucion con delays.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Leer una combinacion
« Respuesta #10 en: 12 de Marzo de 2017, 12:44:43 »
Este es un problema típico de máquina de estados.
https://es.wikipedia.org/wiki/Aut%C3%B3mata_finito



Para resolver un problema así, primero hay que diseñar la máquina de estados.
Esto se hace dibujando unos círculos, que son los estados en los que puede estar el sistema y luego dibujando unas líneas, que son las condiciones para pasar de un estado a otro.

Una vez que la máquina de estados está clara, sólo hay que programarla en cualquier lenguaje.

Algunos programadores con experiencia pueden programar directamente una máquina de estados sin haberla dibujado ni haberla imaginado. Los resultados no suelen ser muy buenos, así que imagínate en tu caso que no tienes experiencia.

Ya que estás aprendiendo, lo mejor es comenzar haciéndolo bien.
He podido ver algunas chapuzas bastante grandes y que han costado retrasos y una buena cantidad de dinero por lanzarse a programar sin analizar antes el problema.

Analizar los estados de la máquina no es sencillo la primera vez. Te propongo los siguientes:
Situación inicial
Primera tecla pulsada
Segunda tecla pulsada
Tercera tecla pulsada
Todo el código correcto

Ahora tienes que definir qué tareas se hacen en cada uno de los estados y qué condición es necesaria para pasar de un estado a otro.

Todo esto es complicado y hay otros caminos más rápidos y sencillos, pero ahí queda eso por si quieres hacer las cosas despacio y bien hechas.

Un saludo.
« Última modificación: 12 de Marzo de 2017, 17:59:45 por Picuino, Razón: Corrección de estilo »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Leer una combinacion
« Respuesta #11 en: 12 de Marzo de 2017, 13:02:04 »
( aquí es donde esta mi problema generar una tarea que acepte las pulsaciones para que al término del tiempo (los 3 segundos),  salga del scaneo y compruebe la combinación, si resulta correcta el contador se pone en 1.
Eso no es un problema, son muchos problemas y están mal definidos.
Antes de solucionar un problema necesitas definir el problema.

¿No sabes cómo aceptar pulsaciones? Imagino que te refieres a leer la pulsación. Se lee por ejemplo con:
value = PORTBbits.RB0;
¿Es ese tu problema o es otro?

En cuanto al scaneo de tres segundos, desde mi punto de vista está mal definido. ¿Tienes que esperar siempre tres segundos y sólo al terminar los tres segundos se comprueban las teclas, tal y como comentas? ¿o se puede dar por terminado el 'escaneo' una vez pulsadas las 4 teclas sin esperar al final de los 3 segundos?

¿Qué pasa si te equivocas en el código introducido? ¿Se queda todo bloqueado o en algún momento se vuelve a aceptar otro código? ¿Cómo se hace eso, por tiempo? ¿En ese caso se indica de algún modo que la máquina vuelve a esperar un código desde el principio?

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Leer una combinacion
« Respuesta #12 en: 12 de Marzo de 2017, 13:10:07 »
Las pulsaciones en sí son también un problema ¿Qué es una pulsación?

Puedes definirla como una entrada que se encuentre en estado alto. Esto es sencillo, pero tiene el problema de leer muchas pulsaciones seguidas aunque tú sólo has presionado una vez.
Otra definición de pulsación es que el estado pase de nivel bajo a nivel alto. Esto es más robusto y evita leer muchas pulsaciones aunque mantengas presionado el pulsador, pero todavía hay que eliminar los rebotes.
También hay quien define la pulsación como pasar de nivel bajo a nivel alto y luego volver a nivel bajo. En este caso la pulsación sólo se acepta cuando dejas de presionar el pulsador.

Si lo defines de la primera manera, no podrás poner combinaciones como 1122, porque se resolverán pulsando sólo el 1 y luego el 2, sin presionar dos veces el 1 y dos veces el 2.

¿A qué nivel de detalle quieres llegar?
Tu decides.

Desconectado raul6162

  • PIC10
  • *
  • Mensajes: 19
Re:Leer una combinacion
« Respuesta #13 en: 12 de Marzo de 2017, 22:50:09 »
Este es un problema típico de máquina de estados.

Una vez que la máquina de estados está clara, sólo hay que programarla en cualquier lenguaje.

Algunos programadores con experiencia pueden programar directamente una máquina de estados sin haberla dibujado ni haberla imaginado. Los resultados no suelen ser muy buenos, así que imagínate en tu caso que no tienes experiencia.

Ya que estás aprendiendo, lo mejor es comenzar haciéndolo bien.
He podido ver algunas chapuzas bastante grandes y que han costado retrasos y una buena cantidad de dinero por lanzarse a programar sin analizar antes el problema.

Analizar los estados de la máquina no es sencillo la primera vez. Te propongo los siguientes:
Situación inicial
Primera tecla pulsada
Segunda tecla pulsada
Tercera tecla pulsada
Todo el código correcto

Ahora tienes que definir qué tareas se hacen en cada uno de los estados y qué condición es necesaria para pasar de un estado a otro.




Tienes toda la razón a mi se me dificulta muy bien el sentar las ideas uno se acostumbra a ir directo a código cuando se esta contra tiempo, conozco el tema de maquinas de estados de hecho me gusto en la materia de "dispositivos lógicos programables" ahí vi los tipos de diseño como Morgan los fpga y cpld son un mundo totalmente distinto y su programación en HDL.
Aquí mi problema fue como bien dices no haber definido el algoritmo para escanear los nivel altos de los push obtenidos en ese tiempo, y sus casos. gracias por el recordatorio.

Desconectado raul6162

  • PIC10
  • *
  • Mensajes: 19
Re:Leer una combinacion
« Respuesta #14 en: 12 de Marzo de 2017, 22:55:53 »
Código: C
  1. int8 patron[4]={0b0001,0b0010,0b0100,0b1000};
  2. int8 i,indice;
  3. int8 valoranterior, valoractual;
  4. itn1 codigocorrecto
  5.  
  6.  
  7. while(1)
  8. {
  9.  
  10.         // Muestro lo que debe introducir
  11.         for( i=0 ; i < sizeof patron; i++)
  12.         {
  13.                 output_c(patron[i]);
  14.                 delay_ms(800);
  15.         }
  16.  
  17.         //Espero que se suelten todos los botones
  18.         //Agregar aca el codigo para eso
  19.  
  20.  
  21.         codigocorrecto = 0;
  22.         valoranterior = 0;
  23.  
  24.         // Procedo a leer los pulsadores por un tiempo de 60 x 50ms = 3000ms
  25.         // Si quisiera auemntar el tiempo, aumentaria el valor que debe alcanzar i, ejemplo
  26.         // si quisiera 6s aumentaria la condicion del for a i < 120 ( 120x50ms = 6000ms )
  27.  
  28.         for( i=0, indice=0; i < 60; i++)
  29.         {
  30.                 // Compruebo primero que lo presionado sea distinto a la anterior pasada del for
  31.                 valoractual = LecturaPort & 0b1111;
  32.                 if (valoractual != valoranterior)
  33.                 {
  34.                         //Si es distinto entra aca, de esa forma yo se que algo cambio desde lo que se presiono antes
  35.                         //Este es el caso en que se presione un boton o muchos o directamente se suelten todos
  36.                         // No debo tomar cuando se suelten todos, asi que pregunto que para entrar posea algo presionado
  37.                         if(valoractual != 0)
  38.                         {
  39.                                 //Aca hay algo presionado, solo me queda confirmar que lo presionado sea lo mismo que mostramos
  40.                                 //Por eso compruebo en orden que se cumpla
  41.                                 if(patron[indice] == valoractual)
  42.                                 {
  43.                                         //Si entro aca quiere decir que el valor que se presiono fue correcto
  44.                                         // Asi que aumento el indice para el proximo valor a presionar
  45.                                         indice++;
  46.                                         // En caso de que se pusieron todos los valores entonces salgo y marco como correcto
  47.                                         if(indice>=sizeof patron)
  48.                                         {
  49.                                                 //Codigo Completo
  50.                                                 codigocorrecto=1;
  51.                                                 break;
  52.                                         }
  53.                                 }
  54.                                 else
  55.                                 {
  56.                                         //Aca se introdujo otro valor no correcto
  57.                                         //Procedo a salir
  58.                                         break;
  59.                                 }
  60.                         }
  61.                 }
  62.                 delay_ms(50);
  63.                 valoranterior = valoractual;
  64.         }
  65.  
  66.         if(codigocorrecto == 1)
  67.         {
  68.                 //Aca lo del codigo correcto
  69.         }
  70.         else
  71.         {
  72.                 //Aca lo del codigo incorrecto
  73.         }
  74.  
  75. }

Personalmente me gustaria mas una solucion con un timer, pero aca tenes una solucion con delays.

Debo decir que diste en el clavo la verdad, aun no tengo mucha experiencia con el manejo de tiempos de hecho ni siquiera he trabajado los timers en mi materia el profe es como si no existiese, hoy de hecho me comentaron de una técnica para no usar el dalay con  los push un candado con while, que seria así:

                           if(botón==1){
                           while(botón==1){}
                           .
                           .
                           .
                           }
de este modo mientras este presionado no acepta otra instrucción pues estará atorado en el while hasta soltarse el push botón.
la verdad me dejo un sabor de boca amargo ver lo formal, limpio y bien estructurado de tu código ((:-)), yo sigo siendo basante secuencial en ese sentido xD
« Última modificación: 12 de Marzo de 2017, 23:02:08 por raul6162 »


 

anything