Autor Tema: Botones y PIC16F1829 (Para introducir password)  (Leído 2704 veces)

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

Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Botones y PIC16F1829 (Para introducir password)
« en: 07 de Abril de 2015, 08:59:02 »
Hola compañeros, soy nuevo por aquí. He estado investigando por el foro como invitado y al final he decidido registrarme para ayudar en lo posible, soy un novato y como no pues me presento con una duda. Estoy implementando un código que en un futuro me servirá para introducir mediante botones una contraseña para iniciar un menu en el LCD.

Para ello he puesto dos botones los cuales servirán para subir y bajar un numero (0...9999) que muestro por el LCD, hasta llegar al valor deseado y con un tercer botón aceptarla.

Mi problema viene que los botones no me hacen caso y los tengo definidos en los puertos que tocan. Si entras en propiedas en proteus su estado {STATE=0} sin embargo con el proteus 7 hago simulacion paso a paso y me salen con valor 1. ¿Eso imagino que vendrá dado por la configuracion de las resistencias pullup?¿O estoy equivocado?

Bueno aqui os enseño el código:

#define Pulse_arriba PIN_B7
#define Pulse_abajo  PIN_C3

void main(void){

lcd_init();


int Arriba=input(Pulse_arriba);
int Abajo=input(Pulse_abajo);

signed int pulsa=0;

lcd_gotoxy(1,1);
lcd_putc("Contraseña: \n");

while(1){

     if(!Arriba){
     pulsa++;     
     lcd_gotoxy(3,2);
     printf(lcd_putc,"%d",pulsa);
                }
                 
    if(!Abajo) {
     pulsa--;
     lcd_gotoxy(3,2);
     printf(lcd_putc,"%d\n",pulsa);
               }
     
     
     if(pulsa==9999){
     pulsa=0;}

}


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #1 en: 07 de Abril de 2015, 10:17:17 »
Con resistencia de pullup ( no se por que no tiene definida una resistencia en proteus y dice PULLUP, ponele 10K ) tendrias un 1 si no esta presionado.

Citar
while(1){
     if(!Arriba){
     pulsa++;    
     lcd_gotoxy(3,2);
     printf(lcd_putc,"%d",pulsa);
                }
                  
    if(!Abajo) {
     pulsa--;
     lcd_gotoxy(3,2);
     printf(lcd_putc,"%d\n",pulsa);
               }
    
    
     if(pulsa==9999){
     pulsa=0;}
}  

Por otra parte tu programa no va a hacer nada. Abajo y Arriba lo lees una ves antes de entrar a se while y nunca mas. Entonces quedarian en 1 y 1 y jamas cambiarian, como si jamas se hubieran presionado ya que no lo lees mas. Abajo y Arriba son variables que les asignaste un valor y nunca mas cambiaron.
Algo asi seria lo correcto, espero haberme hecho entender.

Código: C
  1. if(!input(Pulse_arriba)){
  2.      pulsa++;    
  3.      lcd_gotoxy(3,2);
  4.      printf(lcd_putc,"%d",pulsa);
  5.                 }
  6.                  
  7.     if(!input(Pulse_abajo)) {
  8.      pulsa--;
  9.      lcd_gotoxy(3,2);
  10.      printf(lcd_putc,"%d\n",pulsa);
  11.                }
  12.      
  13.      
  14.      if(pulsa==9999){
  15.      pulsa=0;}
  16. }

O podes poner el int Abajo=.... y del arriba dentro del while, por encima de los if y tendrias el mismo resultado ( aunque no tiene sentido crear variables para algo que no es necesario :P )

Otra de las cosas es el antirebote (ya que los switch reales dan varios pulsos antes de quedar en un estado definido) o si lo tenes presionados no cuente muchas veces. vos tenes que imaginarte que ese codigo se hace muchas veces desde que presioans el boton hasta que lo soltas y puede que te cuente 2,3 o 100 antes que te lo soltes.

Soluciones hay, o un antirebote por hardware o por software + una limitante que solo sume 1 cada ves que lo persionas, lo mas simple seria algo asi:

Código: C
  1. if(!input(Pulse_arriba)){
  2.                 delay_ms(50);
  3.                 while(!input(Pulse_arriba));
  4.                 pulsa++;    
  5.                 lcd_gotoxy(3,2);
  6.                 printf(lcd_putc,"%d",pulsa);
  7.                 }

el delay funcionaria como un antirebote y el while hace que solo cuando soltes el boton cuente 1. es decir tenes que presionarlo y luego soltarlo para que proceda.
Tambien deberias definir esta directiva para que funcione el delay_ms(); al comienzo del programa arriba de los defines

#use delay (clock=20000000)

El numero que pones ahi es la frecuencia que estas trabajando, si tu cristal es de 40Mhz, pones 40000000, si tu oscilador interno es de 8Mhz pones 8000000.

Por otra parte pensaste que si tenes el numero 2790 tenes que presionar 2790 veces el boton ? :/ Al menos en este ejemplo :)
Teniendo 4 botones podrias hacer de izquierda derecha, y solo modificar 1 a 1 los numeros.
« Última modificación: 07 de Abril de 2015, 10:25:36 por KILLERJC »

Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #2 en: 07 de Abril de 2015, 11:41:21 »
Hola KILLERJC, ante todo muchas gracias. Ya he entendido a lo que te refieres, mi fallo era que no comprobaba si había cambiado el valor del botón porque solo lo comprobada al principio :), gracias. Ya lo he corregido y por ahora funciona.

En cuanto a lo que me comentas, mi idea era que al pulsar un botón durante un tiempo prolongado ascendiera más rápido el contador.

Por ahora estoy haciendo pruebas para aceptar una contraseña cercana a 0 para no perder mucho tiempo seleccionándola.

 if(pulsa==10 && (!input(Pulse_enter))){
                  delay_ms(50);
                  lcd_putc("\f");
                  lcd_putc("Contraseña correcta");
                   
                  }

Por ahora no me funciona, ya que si le doy al botón ENTER directamente me limpia la fila de abajo del LCD.

Un saludo y muchas gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #3 en: 07 de Abril de 2015, 11:48:14 »
parece ser que es problema de como mostrar en el LCD

probaste con:

printf(lcd_putc,"\f");
printf(lcd_putc,"Contraseña correcta");

Sino pone el codigo y lo vemos por si es otra parte.


Otra cosa:

Código: [Seleccionar]
signed int pulsa=0;
me preocupa que tenga signo, no deberia.. Deberia ser unsigned y no solo comprobar que el maximo sino tambien el minimo, con uan simple comparacion lo haces si es unsigned

Código: [Seleccionar]
if(pulsa>9999){pulsa=0;}
« Última modificación: 07 de Abril de 2015, 12:05:17 por KILLERJC »

Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #4 en: 07 de Abril de 2015, 12:16:55 »
Hola KILLERJC, ante todo otra vez gracias. El problema que tengo es que el botón ENTER me sale como que esta presionado, por lo tanto cuando voy moviendo números y llego al password directamente me la da como buena sin necesidad de pulsar el botón ENTER.

Aquí te pongo el código general.

#include <16f1829.h>

#use delay(clock=4000000)

#include "flexi_lcd.c"

#include<string.h>

#fuses xt,HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT

#define Pulse_escape PIN_A1
#define Pulse_enter  PIN_A3
#define Pulse_arriba PIN_B7
#define Pulse_abajo  PIN_C3

void main(void){

lcd_init();

unsigned int pulsa=0000;

lcd_gotoxy(1,1);
lcd_putc("Password: \n");

while(1){

    if(!input(Pulse_arriba)){
                delay_ms(50);
                while(!input(Pulse_arriba));
                    pulsa++;    
                    lcd_gotoxy(4,2);
                    printf(lcd_putc,"%d",pulsa);
                            }
                  
    if(!input(Pulse_abajo)) {
                delay_ms(250);
                while(!input(Pulse_abajo));
                      pulsa--;
                      lcd_gotoxy(4,2);
                      printf(lcd_putc,"%d",pulsa);
                            }
                            
       if(pulsa==3){
               if(!input(Pulse_enter)){
                  delay_ms(50);
                  lcd_gotoxy(10,2);
                  lcd_putc("Pass OK");
                  //printf(lcd_putc,"\f");
                  //printf(lcd_putc,"Contraseña correcta");
                  }
    }
                  
                                              
      if(pulsa>9999 || pulsa<0000){
                pulsa=0;}
}
}      


Gracias por la velocidad de contestación. Un saludo          
« Última modificación: 09 de Abril de 2015, 04:01:31 por hortoedro »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #5 en: 07 de Abril de 2015, 20:02:41 »
La verdad es que no deberia el if esta bien definido. En el proteus ves que tiene un 1 en esa entrada ?




Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #6 en: 08 de Abril de 2015, 03:25:12 »
La verdad es que no deberia el if esta bien definido. En el proteus ves que tiene un 1 en esa entrada ?





Hola compañero, gracias por la ayuda. He cambiado de botón a otro que entra al PIC por distinta entrada y si que funciona. Más adelante miraré a ver que pasa con ese :( :(

Por cierto KILLERJC , lo que me comentaste de subir el conteo mediante 4 botones y elegir si quiero subir unidades/centenas/decenas y así ascender más rápido en mi caso no es posible, ya que tengo un menú con distintas opciones, y necesito un botón de ENTER y otro de ESCAPE para ir por el menú. Por tanto solo podría utilizar subir y bajar para variar el password, aún así muchas gracias.

En cuanto a lo de ascender más rápido el conteo conforme más tiempo esta pulsado el botón, estoy pensando en como hacerlo y no lo tengo muy claro. ¿Sería con un delay_ms en una condición junto con el botón pulsado?

Es decir, algo así:
 
if(!input(Pulse_arriba) && delay_ms(2000))

Nose si será una locura o no jaja. Voy a probar.

Saludos y gracias

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #7 en: 08 de Abril de 2015, 05:39:36 »
No, por que el delay es solamente hacer que le microcontrolador ejecute muchas veces instrucciones NOP o SALTOS que directamente no hacen nada al programa, no es que genera una ventana que se cumpla por ese tiempo. Si de C traducis a ASM o entendes como funciona C

esto:

if(!input(Pulse_arriba) && delay_ms(2000))

Haria:

Se fija si la primera condicion de cumple, de no cumplirse la segunda no importa y no entra en el if. De cumplirse hace la otra condicion, en este caso ejecutaria el delay haciendo Nada por 2s. y entraria al If o no (no creo que devuelva nada la funcion, lo cual se podria considerar NULL y que no entre al If) pero no funciona como vos pensas.

Formas de hacerlo hay varias la mas facil que se me ocurre es algo asi:

Código: [Seleccionar]
   if(!input(Pulse_arriba)){
                delay_ms(500 - rapidez);
                    pulsa++;    
                    lcd_gotoxy(4,2);
                    printf(lcd_putc,"%d",pulsa);
                    if (rapidez < 450) { rapidez += 5 ;}
                            }
    if(input(Pulse_arriba) && input(Pulse_abajo)){ rapidez =0; }

Debo sacar el while por que no funcionaria como quiero, basicamente lo que hago es comenzar con un delay de 500ms ( o tal ves mas ), si sigo teniendo presionado rapidez aumenta de 5 en 5 o el valor que yo quiera ( 1, 2 , 3, etc ) disminuyendo mi delay.
Es decir cada ves que entra disminuye el tiempo entre que va aumentando pulsa, cuando soltas ( ambos botones ) se reinicia el valor rapidez.

Luego tenes formas mas complejas hasta de hacer interrupciones con el timer y observar los pines cada 1ms por ejemplo, y fijar que cada xx segundos comienze a ir mas rapido.

Si queres hacer escalones, es decir que si mantenes presionado, por 5 segundos suba a una velocidad, por otros 5 a otra y por ultimo una maxima velocidad, simplemente modificas esto:

Código: [Seleccionar]
                   if (rapidez < 450) { rapidez += 5 ;}
por algo asi:

Código: [Seleccionar]
                   if (rapidez < 50) { rapidez += 5 ;}
                    else if (rapidez < 200) { rapidez += 10 ;}
                    else if (rapidez < 450) { rapidez += 20 ;} // Esta condicion si o si, ya que es la que impone el limite maximo de reduccion del delay.

O con un switch case.
CREO que deberia andar bien lo que digo :), rapidez es una variable de 16bits en este caso

Citar
Por cierto KILLERJC , lo que me comentaste de subir el conteo mediante 4 botones y elegir si quiero subir unidades/centenas/decenas y así ascender más rápido en mi caso no es posible, ya que tengo un menú con distintas opciones, y necesito un botón de ENTER y otro de ESCAPE para ir por el menú. Por tanto solo podría utilizar subir y bajar para variar el password, aún así muchas gracias.

Podrias...
Comenzado con el primer digito, tenes para subir o bajar ( o directamente subir solo ya que son 10 opciones ) y luego un Enter y pasas al segundo digito, asi hasta el 4to donde ese ultimo Enter comprueba el numero ingresado.
O del ultima como dije solo seria necesario subir, por lo tanto tendrias un boton de subir, atras, enter y podes usarlo al otro como para pasar al otro digito ( ejemplo hacia la derecha ). Esto te permitiria mofidicar el valor por si le erraste en algun numero.
« Última modificación: 09 de Abril de 2015, 03:27:10 por KILLERJC »

Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #8 en: 09 de Abril de 2015, 03:15:43 »
Hola KILLERJC, perdona por la tardanza que he estado liado. He probado el código que me comentas para al presionar un botón (Pulse_arriba) ascendiera más rápido el conteo y no funciona. Lo presiono durante bastante rato y cuando suelto solo me cuenta uno, no entiendo porque  :? .

rapidez la he declarado como un int.

"cuando soltas ( ambos botones ) se reinicia el valor rapidez"

¿A que te refieres con ambos botones? ¿Qué ambos botones?

Saludos y gracias

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #9 en: 09 de Abril de 2015, 03:26:47 »
Citar
Hola KILLERJC, perdona por la tardanza que he estado liado. He probado el código que me comentas para al presionar un botón (Pulse_arriba) ascendiera más rápido el conteo y no funciona. Lo presiono durante bastante rato y cuando suelto solo me cuenta uno, no entiendo porque

Le sacaste el while(!input(Pulse_arriba)); ?

Citar
¿A que te refieres con ambos botones? ¿Qué ambos botones?

    if(input(Pulse_arriba) && input(Pulse_abajo)){ rapidez =0; }

Sino postea el codigo y lo vemos

Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #10 en: 09 de Abril de 2015, 03:36:58 »
Hola KILLERJC, ya vi lo de los dos botones, es que anteriormente me salían ambos botones con Pulse_arriba en esa linea de código pero ya veo que lo has editado, ahora ya lo comprendo.


EDITO:

Al final ya he conseguido hacerlo, le estaba dando vueltas y ya funciona, aquí pongo el código por si a alguien le hiciera falta.


Código: [Seleccionar]

     if(Arriba) {
                delay_ms(250);
                 if(!Arriba){
                      pulsa++;
                      lcd_gotoxy(4,2);
                      printf(lcd_putc,"%d",pulsa);
                                         }
                 else {
                 if(Arriba){
                      pulsa=pulsa+10;
                      lcd_gotoxy(4,2);
                      printf(lcd_putc,"%d",pulsa);
                 }
                 }          
               }


Lo primero que hace es comprobar si el botón de Arriba está pulsado, si lo esta, comprueba si ha cambiado de valor el pulsador o no. Si ha cambiado de valor significa que ha sido pulsado y soltado, entonces suma a pulsa el valor de 1. Si no ha cambiado de valor significa que sigue pulsado, por tanto pulsa suma de 10 en 10 hasta soltar el botón.

Gracias KILLERJC

Un saludo.
« Última modificación: 09 de Abril de 2015, 05:15:09 por hortoedro »

Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #11 en: 09 de Abril de 2015, 07:56:22 »
Hola otra vez, la variable pulsa que me almacena el valor de la contraseña solo me llega hasta 122 .  :? :?

La he declarado así:

Código: [Seleccionar]
unsigned int pulsa=0;
es de 8 bits, por tanto me dará valores hasta 256. Según mis conocimientos, son -128...128. Pero si lo declaro como unsigned... ¿No debería de darme los 256 positivos?

Sino, ¿Como deberia declararla para que me diese valores hasta 999?

Buscando por google vi que podría declararla como short pero al variar el valor de pulsa para poner la contraseña no me pasa del 0 y del 1 :? :?

Saludos y gracias.
« Última modificación: 09 de Abril de 2015, 08:00:16 por hortoedro »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #12 en: 09 de Abril de 2015, 08:53:39 »
para CCS la variable si no me equivoco es int16

Desconectado hortoedro

  • PIC10
  • *
  • Mensajes: 19
Re: Botones y PIC16F1829 (Para introducir password)
« Respuesta #13 en: 09 de Abril de 2015, 10:56:49 »
para CCS la variable si no me equivoco es int16

OK, gracias. Un saludo