Teclado touch-sensor para Arduino

Todo cuanto tiene que ver con la obtención, almacenamiento y proceso de la información digital, sus aplicaciones y el software y hardware utilizado.
Responder
Mensaje
Autor
Avatar de Usuario
Rovellat
Mensajes: 9611
Registrado: Mar May 26, 2009 9:39 pm
Ubicación: Palma de Mallorca (España)

Teclado touch-sensor para Arduino

#1 Mensaje por Rovellat »

( De 6 teclas, pero es facilmente escalable, tanto por arriba, como por abajo)

Me está dando una guerra tremenda; creía que estaría listo en tres patadas, y ya llevo venticinco; :( pero es normal, estoy muy oxidado.

Bueno, la idea original era un teclado antivandálico, (mas o menos); pero no he encontrado nada que me interesase, son todo accesorios para otras cosas concretas, y caros; o sea que me he puesto a inventarlo.

De momento va con 6 teclas efectivas, pero puede llevar mas para despistar, incluso varias teclas juntas, que indiquen que se está intentando violar.

Por ejemplo, supongamos que hay 10 teclas, las 0,2,3,4,8, dan el código correcto, y las 1,5,6,7,9, indican que se está jugando con el teclado; los códigos solo pueden tener combinaciones de 0,2,3,4,8, pero esto solo lo se yo; cualquier intento que tenga uno de los 1,5,6,7,9, no solo es incorrecto, sinó que me puede avisar, o sonar una alarma. Evidentemente los 1,5,6,7,9, van cableados juntos, por lo que solo necesito 6 teclas.

Al final le ha tocado al Arduino hacer el trabajo. Como que la tecla mas robusta es la que no se mueve, me he decantado por los sensores; ya estuve averiguando aquí, que el Arduino tiene una muy alta impedancia de entrada.
Cielo azul sobre campo de mieses, ánimo.
Constitución Española:
Todos los españoles tienen el deber de trabajar y el derecho al trabajo.
Todos los españoles tienen derecho a disfrutar de una vivienda digna y adecuada.

Avatar de Usuario
Rovellat
Mensajes: 9611
Registrado: Mar May 26, 2009 9:39 pm
Ubicación: Palma de Mallorca (España)

Re: Teclado touch-sensor para Arduino

#2 Mensaje por Rovellat »

Un pin configurado como entrada es una antena que capta todo cuanto campo eléctrico se le acerca; no es muy factible, pues hay que controlar la inducción con una resistencia a tierra, de valores muy altos, que no tengo.

Estuve investigando sensores capacitivos, y la idea es muy buena; siempre hay capacidades parásitas, ( y si no se las ponemos) :D . Y el cuerpo humano, es también una capacidad a tierra. Por lo tanto, si cargamos esta capacidad parásita, y miramos el tiempo que tarda en descargarse, este es mayor si estamos tocando el sensor. Solo hay que encontrar el punto.

FUNCIONA; y funciona bién.

No es nuevo, está descrito en la literatura Arduino, pero no se muy bién porque, quizás para hacerlo mas fino controlando mejor el tiempo directamente en C, usan dos pines y una librería.

Lo del pin extra, no me importaba mucho, máxime cuando es común para todas las teclas, pero la librería normalmente hace mas grande el tamaño del sketch, y como el mío todavía tiene que crecer bastante, mejor partir de algo mas pequeño.

Hice unas pruebas, y me funcionó muy bién; tocando directamente el sensor, que es lo que buscaba; puse las funciones básicas aquí, como primicia.
Cielo azul sobre campo de mieses, ánimo.
Constitución Española:
Todos los españoles tienen el deber de trabajar y el derecho al trabajo.
Todos los españoles tienen derecho a disfrutar de una vivienda digna y adecuada.

Avatar de Usuario
Rovellat
Mensajes: 9611
Registrado: Mar May 26, 2009 9:39 pm
Ubicación: Palma de Mallorca (España)

Re: Teclado touch-sensor para Arduino

#3 Mensaje por Rovellat »

Después de probarlo con un solo sensor, tocaba ampliarlo a mas sensores, Como no es cosa de andar tocando el código, sobre todo si hace mas de un día que está escrito. lo mejor es hacer funciones muy compartimentadas y que sean flexibles, por lo tanto se imponía emplear un array. Nueva pelea con los arrays del Arduino aquí.

Ya por fin lo tengo funcionando; he hecho 6 sensores, cada sensor va a su pin, a través de una resistencia de 10K, (opcional); y del pin a tierra, una resistecia de 22M, (obligatoria). los sensores de momento son tornillos M2, en un trozo de plástico. Resistencias, como tengo muy pocas y son de 1/2W, las he soldado con las patas largas, con la intención de recupererlas cuando tenga otras mas adecuadas.

También he hecho una plaquita con 6 LEDs, un cátodo a cada pin de salida de LED, y todos los ánodos juntos, y a través de una resistencia a los +5V. Como solo iban a funcionar de uno en uno para probar, he puesto una sola resistencia, que me sirve, pero ahora me arrepiento, ya que la plaquita me podría servir para otras cosas.
Cielo azul sobre campo de mieses, ánimo.
Constitución Española:
Todos los españoles tienen el deber de trabajar y el derecho al trabajo.
Todos los españoles tienen derecho a disfrutar de una vivienda digna y adecuada.

Avatar de Usuario
Rovellat
Mensajes: 9611
Registrado: Mar May 26, 2009 9:39 pm
Ubicación: Palma de Mallorca (España)

Re: Teclado touch-sensor para Arduino

#4 Mensaje por Rovellat »

Y ya llegamos a los arrays, son dos, el de sensores, y el de leds, cala elemento del array contiene el nº de pin asociado, y ambos arrays están ligados; si pulso el sensor del pin que está en la posición 3 del array de sensores, se encenderá el led del pin que está en la posición 3 del array de leds.

Asi tengo total flexibilidad para cambiar los pines sin tocar el código.

Los LEDs son solo para comprobar el montaje, y depurar el código; evidentemente en el montaje final solo estará el teclado, y los leds, si los hay, se encenderán para otras cosas, no para indicar que se ha pulsado un sensor.
Cielo azul sobre campo de mieses, ánimo.
Constitución Española:
Todos los españoles tienen el deber de trabajar y el derecho al trabajo.
Todos los españoles tienen derecho a disfrutar de una vivienda digna y adecuada.

Avatar de Usuario
Rovellat
Mensajes: 9611
Registrado: Mar May 26, 2009 9:39 pm
Ubicación: Palma de Mallorca (España)

Re: Teclado touch-sensor para Arduino

#5 Mensaje por Rovellat »

Código: Seleccionar todo

// PruebaDededazoCapacitivo3.0
// 6 pulsadores touch-sensor capacitivos facilmente escalables
// Palma de Mallorca, a 10 de Marzo del 17

int sensores[] = {2, 3, 4, 5, 6, 7};  // Pines a los que están conectados los sensores, (6 sensores del 0 al 5)
int numSensores;  // Esta variable tendrá el nº de sensores DECLARADOS EN EL ARRAY ANTERIOR (pines).
int leds[] = {8, 9, 10, 11, 12, 13};  // Pines a los que están conectados los LEDS (uno por sensor). Los sensores y los LDEs, se corresponden
  //por las posiciones respectivas que ocupan en el array. (ejmplo: al pulsar el sensor de la posición 2 se encenderá el LED de la posición 2) 
int umbralAlto = 1400;
int umbralBajo = 1200;
int antiRuido =3;   // Número de confirmaciones antes de dar por buena la pulsación, mas alto es mas preciso, y mas lento
boolean pulsado = false;
int teclaPulsada = -2;
int medida;

void setup()
{
  numSensores = sizeof(sensores)/sizeof(sensores[0]);    // Se supone que averigua el nº de elementos del array (numero de sensores)
  //  Serial.begin(9600); //Iniciamos la comunicación  serial
  for (int sensor = 0 ; sensor < numSensores; sensor++)
  {
    pinMode(sensores[sensor], INPUT);  //Pin del sensor n como entrada (bucle: todos los sensores como entrada)
    pinMode(leds[sensor], OUTPUT);     //Pin del LED n como salida  (bucle: todos los LEDs como salida)
    digitalWrite(leds[sensor],HIGH);   // Pin n a cero   (bucle: todos los LEDs a 5V)
  }
}

void loop() 
{
  while (teclaPulsada <0)   //Bucle hasta que se pulsa un sensor.
  {
    teclaPulsada = leeTeclado(); // Va leyendo el teclado.
  }  
  while (hayTeclaPulsada(2)) //Bucle mientras sigue pulsado un sensor
  {
    digitalWrite(leds[teclaPulsada],LOW);  //Enciende el LED correspondiente, mientras continúe pulsado el sensor
  }
  digitalWrite(leds[teclaPulsada],HIGH);  //Apaga el LED antes de continuar
  teclaPulsada = -3;
}


//     FUNCIONES  //////////////////////
////////////////////////////////////////
int lee(int pata)  // Devuelve una medida relativa proporcional al tiempo de descarga del sensor. (En microsegundos, aproximadamente)
                   // pata es el pin al que va conectado el sensor, a través de una resistencia de 10K
                   // Otra resistencia de 22M, va entre el pin, y masa
{
  float time; 
  digitalWrite(pata,LOW);     //  // Escribe un 0; es decir descarga las capacidades que hubiese en el pin
  delay(3);    // tiempo de descarga
  digitalWrite(pata,HIGH);     // Escribe un 1; es decir carga las capacidades que hubiese en el pin
  delay(8);    // tiempo de carga
  time = micros();
  pinMode(pata, INPUT);
  while (digitalRead(pata) == HIGH);   // repite hasta que lee cero, es decir se han descargado las capacidades, a través de la resistencia 
  time = micros()-time;
  return time;
}  // fin de lee()
////////////////////////////////////////
boolean confirmaSi(int pata , int umbral , int veces)  // Hace varias lecturas consecutivas en el pin,
                                                     //devuelve verdadero si las cinco sobrepasan el umbral
{
  for (int i=0; i < veces; i++) if (lee(pata) < umbral) return false;
  return true;
}
////////////////////////////////////////
int leeTeclado ()    // Devuelve el sensor pulsado, o -1 si no hay ninguno
{
  for (int sensor = 0 ; sensor < numSensores; sensor++)
    {
      if (lee(sensores[sensor]) > umbralAlto)  if (confirmaSi(sensores[sensor],umbralAlto,antiRuido)) return sensor;  
    }
  return -1;
}
////////////////////////////////////////
boolean hayTeclaPulsada(int pasadas)    // Confitma SI todavía está alguna tecla pulsada
{
  for (int i=0; i < pasadas; i++)
  {
    for (int sensor = 0 ; sensor < numSensores; sensor++) 
    {
      if (lee(sensores[sensor]) > umbralAlto) return true;  //Todavía hay algún sensor pulsado
    }
  }
  return false;  // Despues de realizar n pasadas, no ha encontrado ningún sensor pulsado
}
Cielo azul sobre campo de mieses, ánimo.
Constitución Española:
Todos los españoles tienen el deber de trabajar y el derecho al trabajo.
Todos los españoles tienen derecho a disfrutar de una vivienda digna y adecuada.

Avatar de Usuario
Rovellat
Mensajes: 9611
Registrado: Mar May 26, 2009 9:39 pm
Ubicación: Palma de Mallorca (España)

Re: Teclado touch-sensor para Arduino

#6 Mensaje por Rovellat »

Esta es la primera versión de la edición 3, muy mejorable, pero totalmente funcional.

Es quizás un poco lenta de reflejos; pero me vale; el tiempo entre pulsaciones es una codificación añadida.

Pienso que resistencias menores acortarían el tiempo; lo otro es escribir en C; y no estoy de momento por la labor.

Si cambio las resistencias, tendré que recalcular los tiempos; estoy pensando en que lo haga el programa de forma mas o menos automática; pero esto será mas adelante.

Saludos.
Cielo azul sobre campo de mieses, ánimo.
Constitución Española:
Todos los españoles tienen el deber de trabajar y el derecho al trabajo.
Todos los españoles tienen derecho a disfrutar de una vivienda digna y adecuada.

Avatar de Usuario
Rovellat
Mensajes: 9611
Registrado: Mar May 26, 2009 9:39 pm
Ubicación: Palma de Mallorca (España)

Re: Teclado touch-sensor para Arduino

#7 Mensaje por Rovellat »

Haciendo caso al jefe Heli, he pasado el nº de teclas como constante del preprocesador; y ya de paso otras; así ahorro memoria.

Esta es pues la segunda versión, depurada y funcional; pero tiene un cambio muy grande; la inclusión del análisis de los tiempos medios, y su presentación en el monitor serie.

La misión de esto último es para depurar el hardware; ver que todas las teclas funcionan, los tiempos considerados son correctos, y similares entre teclas, etc, y además como pueden variar con cada procesador, es interesante mirar estos tiempos medios.

Con los tiempos medios obtenidos, ya podemos decidir si los umbrales son correctos, y modificarlos en caso de ser necesario.

Una vez hecho esto, todo lo referente a la medida de los tiempos medios, sobra, y puede quitarse.

Además los LEDs y el bucle de prueba, no tienen sentido en un montaje final, por lo que realmente lo único que interesa son las funciones que leen los sensores.

Código: Seleccionar todo

// PruebaDededazoCapacitivo3.1
// 6 pulsadores touch-sensor capacitivos facilmente escalables
// Cada sensor va conectado a su pin a través de una resistencia (opcional) de unos 10K, 
// y del pin a masa (GND) va una resistencia (obligatoria) de unos 22M.
// Palma de Mallorca, a 12 de Marzo del 17
// Ver los comentarios generales al final.

#define umbralAlto 1400  // Por encima de este valor (tiempo) se considera que se ha pulsado el sensor.
#define umbralBajo 900  // Por debajo de este valor (tiempo) se considera que el sensor está sin pulsar.
#define antiRuidoSi 3   // Número de lecturas positivas antes de dar por buena la pulsación; mas alto es mas preciso, y mas lento.
#define antiRuidoNo 2   // Número de lecturas negativas antes de confirmar la NO pulsación; mas alto es mas preciso, y mas lento.
#define DL1 3   // Tiempo de descarga del condensador parásito
#define DL2 8   // Tiempo de carga del condensador parásito
#define numSensores 6 // Esta variable tendrá el nº de sensores DECLARADOS EN EL ARRAY (pines).
int sensores[numSensores] = {2, 3, 4, 5, 6, 7};  // Pines a los que están conectados los sensores, (6 sensores del 0 al 5)
int leds[numSensores] = {8, 9, 10, 11, 12, 13};  // &LED& Pines a los que están conectados los LEDS (uno por sensor). Los sensores y 
  // &LED& los LDEs, se corresponden por las posiciones respectivas que ocupan en el array. (ejmplo: al pulsar el sensor de la posición 2 
  // &LED& se encenderá el LED de la posición 2) 
//int mediaBaja[numSensores] = {450, 450, 450, 450, 450, 450};  // &MEDIA& Va almacenendo los tiempos medios para cada sensor no pulsado
//int mediaAlta[numSensores] = {1300, 1300, 1300, 1300, 1300, 1300};   // &MEDIA& Va almacenendo los tiempos medios para cada sensor pulsado
  // &MEDIA&En el prototipo los valores bajos rondaban los 450, y los altos 4000. Sirven para ayudar a definir umbralAlto, y umbralBajo.
boolean pulsado = false;
int teclaPulsada = -2;



void setup()
{
  //numSensores = sizeof(sensores)/sizeof(sensores[0]);    // Se supone que averigua el nº de elementos del array (numero de sensores)
  //Serial.begin(9600); // &MEDIA& Iniciamos la comunicación  serial, QUITAR O COMENTAR SI NO SE USA,
  for (int sensor = 0 ; sensor < numSensores; sensor++)
  {
    pinMode(sensores[sensor], INPUT);  //Pin del sensor n como entrada (bucle: todos los sensores como entrada)
    pinMode(leds[sensor], OUTPUT);     //Pin del LED n como salida  (bucle: todos los LEDs como salida)
    digitalWrite(leds[sensor],HIGH);   // Pin n a cero   (bucle: todos los LEDs a 5V)
  }
}

void loop() // Es una prueba en bucle del funcionamiento del teclado y las funciones asociadas
{
  while (teclaPulsada <0)   //Bucle hasta que se pulsa un sensor.
  {
    teclaPulsada = leeTeclado(); // Va leyendo el teclado.
  }  
  while (hayTeclaPulsada(antiRuidoNo)) //Bucle mientras continúa pulsado un sensor
  {
    digitalWrite(leds[teclaPulsada],LOW);  //  &LED&  nciende el LED correspondiente, mientras continúe pulsado el sensor
  }
  digitalWrite(leds[teclaPulsada],HIGH);  //  &LED& Apaga el LED antes de continuar
  teclaPulsada = -3;
  //muestraMedias();   // &MEDIA& muestra los valores medios
}


//     FUNCIONES  //////////////////////
////////////////////////////////////////
int lee(int pata)  // Devuelve una medida relativa proporcional al tiempo de descarga del sensor. (En microsegundos, aproximadamente)
                   // pata es el pin al que va conectado el sensor, a través de una resistencia de 10K
                   // Otra resistencia de 22M, va entre el pin, y masa
{
  float time; 
  digitalWrite(pata,LOW);     //  // Escribe un 0; es decir descarga las capacidades que hubiese en el pin
  delay(DL1);    // tiempo de descarga
  digitalWrite(pata,HIGH);     // Escribe un 1; es decir carga las capacidades que hubiese en el pin
  delay(DL2);    // tiempo de carga
  time = micros();
  pinMode(pata, INPUT);
  while (digitalRead(pata) == HIGH);   // repite hasta que lee cero, es decir se han descargado las capacidades, a través de la resistencia 
  time = micros()-time;
  return time;
}  
////////////////////////////////////////
boolean confirmaSi(int pata , int umbral , int veces)  // Hace varias (veces) lecturas consecutivas en el pin,
                                                     //devuelve verdadero si todas sobrepasan el umbral
{
  for (int i=0; i < veces; i++) if (lee(pata) < umbral) return false;
  return true;
}


////////////////////////////////////////
// Hay dos funciones leeTeclado(); usar solo una y comentar la otra
///////////////////////////////////////ESTA ES LA FUNCIÓN leeTeclado ORIGINAL/////////

int leeTeclado ()    // Devuelve el sensor pulsado, o -1 si no hay ninguno
{
  for (int sensor = 0 ; sensor < numSensores; sensor++)
    {
      if (lee(sensores[sensor]) > umbralAlto)  if (confirmaSi(sensores[sensor],umbralAlto,antiRuidoSi)) return sensor;  
    }
  return -1;
}
////////////////////////////////////////
///////////////////////////////////////ESTA ES LA FUNCIÓN leeTeclado MODIFICADA PARA MEDIR TIEMPOS MEDIOS//////////
/*
int leeTeclado ()    // // &MEDIA& Devuelve el sensor pulsado, o -1 si no hay ninguno
{
  int valor;
  for (int sensor = 0 ; sensor < numSensores; sensor++)
    {
      valor = lee(sensores[sensor]);
      if (valor > umbralAlto) 
      {
        mediaAlta[sensor] = (mediaAlta[sensor] + valor )/2;  // Ajusta el valor medio de tecla pulsada
        if (confirmaSi(sensores[sensor],umbralAlto,antiRuidoSi)) return sensor; 
      } 
      else
      {
        mediaBaja[sensor] = (mediaBaja[sensor] + valor )/2;  // Ajusta el valor medio de tecla no pulsada
      }
    }
  return -1;
}
*/

////////////////////////////////////////
boolean hayTeclaPulsada(int pasadas)    // Confitma SI todavía está alguna tecla pulsada
{
  for (int i=0; i < pasadas; i++)
  {
    for (int sensor = 0 ; sensor < numSensores; sensor++) 
    {
      if (lee(sensores[sensor]) > umbralAlto) return true;  //Todavía hay algún sensor pulsado
    }
  }
  return false;  // Despues de realizar n pasadas, no ha encontrado ningún sensor pulsado
}
////////////////////////////////////////
/*
void muestraMedias()   //  &MEDIA&  Muestra por salida serie los tiempos medios de las teclas no pulsadas, y pulsadas.
  //  Esta función es solo para mostrar en el monitor serie los valores medios del prototipo; quitar en el sketch operativo.
  //  Los valores altos solo se actualizan al haber pulsado el sensor correspondienete.
{
  for (int sensor = 0 ; sensor < numSensores; sensor++) 
  {
    Serial.print ("sensor");  
    Serial.print (sensor); 
    Serial.print (": ");   
    Serial.print (mediaBaja[sensor]);  
    Serial.print ("--");  
    Serial.println (mediaAlta[sensor]);
  }
  Serial.println (" ");  
}
*/
////////////////////////////////////////

/* COMENTARIOS A ESTE SKETCH
Se trata de unas rutinas le lectura de teclado capacitivo; además tiene un bucle de test demostrativo, que enciende un led para cada sensor
pulsado. También tiene una ayuda opcional para medir los tiempos medios en cada montaje concreto.
Evidentemente el interés solo son las rutinas de lectura del teclado; que se incluirán en otros sketchs diferentes; el resto es solo para
demostración, comprobación, y ajuste de los valores de umbral.
*/

/* COMENTARIOS A LOS LEDs
Son solo para probar los sensores y tiempo de reacción; en un sketch definitivo no tienen sentido. Las líneas afectadas vienen marcadas
por &LED& para su localización.
*/


/* COMENTARIOS A LOS VALORES MEDIOS
Este sketch funciona comparando las medidas de tiempo de descarga del condensador parásito, con los valores umbralAlto, y umbralBajo, pero
cada montaje puede requerir ajustes diferentes. Se ha implementado el código necesario para leer los valores medios de cada tecla, sin pulsar
y pulsada. Este código está todo comentado, por lo que hay que descomentarlo para usarlo; después de leidos los valores, ajustar umbralAlto,
y umbralBajo y desactivar de nuevo este código comentando de nuevo las líneas.
Todo el código asociado, está marcado por &MEDIA&, para que sea mas facil buscarlo.
Básicamente es:
int mediaBaja[numSensores] = {450, 450, 450, 450, 450, 450};  // &MEDIA& Va almacenendo los tiempos medios para cada sensor no pulsado
int mediaAlta[numSensores] = {1300, 1300, 1300, 1300, 1300, 1300};   // &MEDIA& Va almacenendo los tiempos medios para cada sensor pulsado
Serial.begin(9600); // &MEDIA& Iniciamos la comunicación  serial, QUITAR O COMENTAR SI NO SE USA,
y las funciones:
leeTeclado(), que tiene dos versiones, la original, y la versione modificada para leer valores medios; (usar solo una), y 
muestraMedia(), que es solo solo para mostrar los datos por el monitor serie.
*/


NOTA: Para mayor legibilidad, pasar el código al IDE de Arduino.

Saludos.
Cielo azul sobre campo de mieses, ánimo.
Constitución Española:
Todos los españoles tienen el deber de trabajar y el derecho al trabajo.
Todos los españoles tienen derecho a disfrutar de una vivienda digna y adecuada.

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados