Muy buenas.
Tengo el siguiente problema para resolver. Tengo puesto en el pin A0 unos pulsadores con sus resistencias, es decir he montado un "teclado" de 7 botones los cuales leo el valor con este código;
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define I2C_ADDR 0x3F // La dirección I2C del LCD
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
int a=0;
void setup()
{
lcd.begin(20, 4);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
}
void loop()
{
a = analogRead(0);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" analogRead() ");
lcd.setCursor(0,1);
lcd.print(" valor es :");
lcd.print(a);
delay(250);
}
Hasta aquí todo bien. El problema es que es muy inestable. Por ejemplo leyendo el segundo pulsador me da un valor de 145 y a veces 149. Luego tengo otro código por el cual con un case y break defino este dato. El problema es cuando en el case porgo;
case 145:
hay veces que no lo coje debido a que el valor es 148 y entonces no me lee el pulsador, me imagino que es por tolerancias de las resistencias y de la alimentación. Entonces como le puedo decir al case que lea desde 140 hasta 160 y me reconozca el dato dandole amplitud de tolerancia?
Agradezco sus ayudas. Gracias!
Porque no prueba con el condicional if?
Ejemplo:
if(a>144 && a<160){ //Aquí defines un rango en el cual si la var. a se sitúa entre los valores
//de 145 y 159 ejecutarás la acción que esté entre las llaves.
Aquí realizas la acción que necesites
}
Saludos.
Lo he probado y no me funciona.
Este es el código que estoy usando;
void handleKeys() {
// unsigned short keyState = analogRead(0);
//const int keyState = analogRead(0);
int keyState = analogRead(0);
if (keyState == 1023 || millis() - lastKeyPress < 100) return;
switch (keyState) {
if (keyState >2 && keyState <15) return;
case 1:
if (radio.state.volume < 15) {
radio.setVolume(radio.state.volume + 1);
displayTimeout = millis() + 5000;
currentDisplay = SHOW_VOLUME;
radio.setMute(false);
lcd.setCursor(0, 3);
lcd.print(" ");
// lcd.setCursor(14, 1);
// lcd.print("STEREO");
}
break;
Ese código es el del teclado del LCD Shield.
Este es un código que puede servirte, mira cual se adapta mejor a tu necesidad.
LCD SHIELD Keyboard
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
/*******************************************************
This program will test the LCD panel and the buttons
Mark Bramwell, July 2010
********************************************************/
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
// read the buttons
int read_LCD_buttons() {
adc_key_in = analogRead(0); // read the value from the sensor
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
// For V1.1 us this threshold
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
// For V1.0 comment the other threshold and use the one below:
/*
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP;
if (adc_key_in < 380) return btnDOWN;
if (adc_key_in < 555) return btnLEFT;
if (adc_key_in < 790) return btnSELECT;
*/
return btnNONE; // when all others fail, return this...
}
void setup() {
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0);
lcd.print("Push the buttons"); // print a simple message
}
void loop() {
lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over
lcd.print(millis()/1000); // display seconds elapsed since power-up
lcd.setCursor(0,1); // move to the begining of the second line
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) { // depending on which button was pushed, we perform an action
case btnRIGHT:
lcd.print("RIGHT ");
break;
case btnLEFT:
lcd.print("LEFT ");
break;
case btnUP:
lcd.print("UP ");
break;
case btnDOWN:
lcd.print("DOWN ");
break;
case btnSELECT:
lcd.print("SELECT");
break;
case btnNONE:
lcd.print("NONE ");
break;
}
}
Este código funciona para el LCD SHIELD de modo que si tu no usas la configuración de resistencias del mismo, no va a responder del mismo modo pero la idea es esa.
Para cada pulsador tendras un min y un máximo, ve anotándolos para cada uno.
Al final tendras una tabla.
La idea es que fijes un extremo de cambio qeu aseguro que toda fluctuación me represente ESA tecla y no otra.
Si miras el código acá hay 5 teclas y tu hablas de 7.
Entonces mira el primero if
if (adc_key_in < 50) return btnRIGHT;
dice que si una tecla en este caso el boton derecho es presionado, se esperan valores menores a 50 unidades del ADC.
Si presionas la tecla P estarás entre 50 y 249
if (adc_key_in < 250) return btnUP;
y de ese simple modo se conforman todas las opciones y te aseguras que no importa como varíe siempre responderá a la tecla correcta.
Muchas gracias Al final . lo he solucionado.
@surbyte ayer estuve toda la tarde con esto, leyendo, revisando he incluso creo que ví la forma que lo hacia la Shield LCD pero aun así no me llegó a funcionar y @mike_117 me dio un poco la luz.
Vale entonces he realizado lo siguiente he definido las variables;
// Definir los botones (Pulsadores)
#define btnVOLMAS 0
#define btnARRIBA 1
#define btnABAJO 2
#define btnVOLMENOS 3
#define btnMUTING 4
#define btnNINGUNO 5
#define btnSTEREO 6
#define btnRESET 7
int tecla_pulsada = 0;
Luego el programa de los valores de las variables;
// Convertir los valores analógicos del pin A0 de Arduino
// Los botones (pulsadores) tienen tolerancias por esto le pongo que no superen
// el valor real y dando un margen del 15% de tolerancia o quizás mejor el 20%
int leer_botones() {
int valor_boton = analogRead(0);
if (valor_boton > 1000) return btnNINGUNO; // Ningun boton
if (valor_boton >2 && valor_boton <10) return btnVOLMAS; // Volumen +
if (valor_boton >499 && valor_boton <515) return btnVOLMENOS; // Volumen -
if (valor_boton >140 && valor_boton <150) return btnABAJO; // Escanear MHz -
if (valor_boton >319 && valor_boton <355) return btnARRIBA; // Escanear MHz +
if (valor_boton >720 && valor_boton <740) return btnMUTING; // Boton Mute
if (valor_boton >830 && valor_boton <845) return btnSTEREO; // Forzar Stereo
if (valor_boton >210 && valor_boton <230) return btnRESET; // Boton Rset
return btnNINGUNO;
}
Si te fijas he logrado de cada botón (pulsador) darle un valor comprendido entre su valor REAL, usando 5 botones no hay problema, el problema viene cuando le he puesto 7, por ello le he dado su "tolerancia"
Entonces con;
void funciones_botones() {
tecla_pulsada = leer_botones();
switch (tecla_pulsada) {
case btnVOLMAS:
if (radio.state.volume < 15) {
radio.setVolume(radio.state.volume + 1);
displayTimeout = millis() + 5000;
currentDisplay = SHOW_VOLUME;
radio.setMute(false);
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.setCursor(14, 1);
lcd.print("STEREO");
}
break;
...
...
...
// mas opciones
..
..
..
}
Con poner en el case la variable del botón, el valor recogido según este ultimo. Como dije estuve toda la tarde y no daba con la solución por ello les pedí ayuda y veo que todo el tiempo empleado aunque no funcionará de esta forma es como uno aprende. Tema solucionado y daros las gracias sin el cual no hubiese funcionado.
Saludos.
El tema de mike y el que yo te puse son lo mismo.
Cada if del ejemplo SHIELD LCD tiene incluido una condición que ya no puede darse.
Te lo expliqué asi que no entiendo como no lo entendiste.
Si el primer if responde a
if (adc_key_in < 50) return btnRIGHT;
el segundo
if (adc_key_in < 250) return btnUP;
responde a todo lo que esta entre 50 y 249, entonces para que poner esto?
[color=#222222]if ([/color][color=#222222]adc_key_in >=50 && [/color][color=#222222]adc_key_in < 250) return btnUP;[/color]
es redundante porque ya esta hecho por la instrucción previa.
Es un código que funciona de ese modo, no puede cambiar el orden de los if porque cada uno esta anidado
al anterior y la función return sale de la función con el valor encontrado.
Si ya lo resolviste no interesa pero mira que código mas simple te queda de este modo comparado
con el tuyo, que nada tiene de malo (aclaro). Solo es relevante cuando tienes mucho código por escribir y
cada byte cuenta.