Touche tactile capacitif sans hardware

Bonjour à tous,

J'ai trouvé ce code qui permet de faire une touche tactile sans matériel.
http://playground.arduino.cc/Code/CapacitiveSensor
Je suis débutant dans le domaine et je ne le comprends pas.
Que faut-il mettre dans void setup et dans void loop?

Pourriez-vous me donner un peu plus d'explications?

J'aimerai par exemple allumer la led de la sortie digitale 13 avec l'entrée digitale 2. Que faut-il ajouter?

Un grand merci d'avance.

// readCapacitivePin
//  Input: Arduino pin number
//  Output: A number, from 0 to 17 expressing
//  how much capacitance is on the pin
//  When you touch the pin, or whatever you have
//  attached to it, the number will get higher
#include "pins_arduino.h" // Arduino pre-1.0 needs this
uint8_t readCapacitivePin(int pinToMeasure) {
  // Variables used to translate from Arduino to AVR pin naming
  volatile uint8_t* port;
  volatile uint8_t* ddr;
  volatile uint8_t* pin;
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
  port = portOutputRegister(digitalPinToPort(pinToMeasure));
  ddr = portModeRegister(digitalPinToPort(pinToMeasure));
  bitmask = digitalPinToBitMask(pinToMeasure);
  pin = portInputRegister(digitalPinToPort(pinToMeasure));
  // Discharge the pin first by setting it low and output
  *port &= ~(bitmask);
  *ddr  |= bitmask;
  delay(1);
  // Make the pin an input with the internal pull-up on
  *ddr &= ~(bitmask);
  *port |= bitmask;

  // Now see how long the pin to get pulled up. This manual unrolling of the loop
  // decreases the number of hardware cycles between each read of the pin,
  // thus increasing sensitivity.
  uint8_t cycles = 17;
       if (*pin & bitmask) { cycles =  0;}
  else if (*pin & bitmask) { cycles =  1;}
  else if (*pin & bitmask) { cycles =  2;}
  else if (*pin & bitmask) { cycles =  3;}
  else if (*pin & bitmask) { cycles =  4;}
  else if (*pin & bitmask) { cycles =  5;}
  else if (*pin & bitmask) { cycles =  6;}
  else if (*pin & bitmask) { cycles =  7;}
  else if (*pin & bitmask) { cycles =  8;}
  else if (*pin & bitmask) { cycles =  9;}
  else if (*pin & bitmask) { cycles = 10;}
  else if (*pin & bitmask) { cycles = 11;}
  else if (*pin & bitmask) { cycles = 12;}
  else if (*pin & bitmask) { cycles = 13;}
  else if (*pin & bitmask) { cycles = 14;}
  else if (*pin & bitmask) { cycles = 15;}
  else if (*pin & bitmask) { cycles = 16;}

  // Discharge the pin again by setting it low and output
  //  It's important to leave the pins low if you want to 
  //  be able to touch more than 1 sensor at a time - if
  //  the sensor is left pulled high, when you touch
  //  two sensors, your body will transfer the charge between
  //  sensors.
  *port &= ~(bitmask);
  *ddr  |= bitmask;

  return cycles;
}

Bonjour,

C'est de la programmation de haut niveau, bien loin de la programmation arduino classique.
Ton code est une fonction toute prête qui vient ce placer âpres setup() et loop() directement dans le corps du code.

Si tu veut un exemple d'utilisation j'utilise exactement le même principe dans mon article ici :

Salut skywood,

Merci pour le lien vers ton site! Mais je l'avais déjà trouvé XD. C'est la première page que j'ai lu à ce sujet et que je trouve très bien faite! Bravo pour ton site.

Ce qui m'intéresse dans le code que j'ai posté, c'est qu'il ne faut aucun composant supplémentaire.
As-tu un lien à me conseiller où je pourrais trouver des infos pour pouvoir utiliser ce code et éventuellement tenter de comprendre le fonctionnement?

Merci et bonne journée.

tomt:
Ce qui m'intéresse dans le code que j'ai posté, c'est qu'il ne faut aucun composant supplémentaire.
As-tu un lien à me conseiller où je pourrais trouver des infos pour pouvoir utiliser ce code et éventuellement tenter de comprendre le fonctionnement?

Les résistances dans mon montage sont des sécurités, tu peut les virer et faire exactement comme dans le code du playground.
On utilise le même principe et quasiment le même code à une boucle prés.

Salut à tous,

Après quelques essais, je n'en suis pas beaucoup plus loin!

J'ai utilisé ton code Skywodd. Mais je n'arrive pas à le faire fonctionne sans résistance externe.
Le programme semble bloquer et n'envoi presque rien sur le moniteur série. Il envoi de temps en temps une valeur qui ne correspond à rien.

J'ai fait un essai en ne lisant que l'entrée 9 et avec une résistance:

const uint16_t THRESHOLD = 50; /* Seuil de détection */
void setup() {
  Serial.begin(115200);   /* Initialise le port série à 115200 bauds */
  /* Aucune initialisation requise des broches "tactiles",
   * la fonction touch_measure() se charge de tout ;)*/
}
void loop() {
  /* Pour la broche  D9 (1 touche) */
  for (uint8_t i = 9; i < 10; ++i){
    if(touch_measure(i) > THRESHOLD){ /* Test si la "touche" a été appuyé ou non */
      Serial.print(touch_measure(i));
      Serial.println();
    }
  }
  delay(100);  /* Délai no-flood */
}

Voici le résultat que j'obtiens quand je touche l'entrée:

212
47
55
7
54
109
194
47

Ça fonctionne mais ce que je ne comprends pas pourquoi j'ai un 7? Le minimum devrait être 50 non?

Lorsque je fais le test sans résistance, j'obtiens un peu n'importe quoi! La carte envoi beaucoup de valeurs mais il n'y a aucune différence si je touche l'entrée ou pas.

Bête question de débutant: ne manque-t-il pas les accolades dans le code après le if ?

for (uint8_t i = 2; i < 12; ++i){
 
    /* Test si la "touche" a été appuyé ou non */
    if(touch_measure(i) > THRESHOLD)
      Serial.print('1');
    else
      Serial.print('0');
 
    //Serial.println(touch_measure(i), DEC);
 
    /* Sépare chaque bits */
    Serial.print(' ');
  }

Mes excuses pour le retard de ma réponse!

Merci d'avance pour votre aide.

tomt:
Ça fonctionne mais ce que je ne comprends pas pourquoi j'ai un 7? Le minimum devrait être 50 non?

Ça devrait pas afficher 7 ...
Refait quelques tests pour voir, c'est peut être juste un probléme d'affichage isolé.

tomt:
Lorsque je fais le test sans résistance, j'obtiens un peu n'importe quoi! La carte envoi beaucoup de valeurs mais il n'y a aucune différence si je touche l'entrée ou pas.

Ralala j'ai dit une connerie dans mon précédent post sans même m'en rendre compte.
Les résistances de mon montage servent de résistance de tirage à +5v (pas de sécurité).
Pas de résistances = fils "en l'air" = antenne = bruit

Dans le setup() fait un :

pinMode(9, INPUT_PULLUP);

ou :

pinMode(9, INPUT);
digitalWrite(9, HIGH);

ça devrait régler tes problèmes sans les résistances.

tomt:
Bête question de débutant: ne manque-t-il pas les accolades dans le code après le if ?

Qu'en il n'y a qu'une instruction les accolades sont facultatives.

Salut,

J'ai refait quelques tests mais j'ai toujours le même problème! j'ai régulièrement des valeurs inférieures à 50 qui s'affichent. Bizarre!

Concernant la résistance de Pullup, je ne constate pas de différence avec ou sans: J'ai enfiché une épingle sur l'entrée 9.
-Lorsque je ne touche rien, il n'y a aucune valeur qui s'affiche dans le moniteur.
-Dés que j'approche mon doigt à moins de 2 cm et même sans toucher, les valeurs défilent dans le moniteur.

J'ai lu que la résistance interne de Pullup est de 20K, C'est assez? http://arduino.cc/en/Tutorial/DigitalPins

Merci pour l'info concernant les accolades!

Bien à vous

tomt:
J'ai refait quelques tests mais j'ai toujours le même problème! j'ai régulièrement des valeurs inférieures à 50 qui s'affichent. Bizarre!

Je comprend vraiment pas pourquoi ça fait ça ...

tomt:
-Dés que j'approche mon doigt à moins de 2 cm et même sans toucher, les valeurs défilent dans le moniteur.

C'est normal, si tu as une charge électrostatique sur toi (pull en laine, synthétique, ...) tu fait commuter la broche sans même la toucher (antenne).
C'est le principe des détecteurs "EMF" du reste.

tomt:
J'ai lu que la résistance interne de Pullup est de 20K, C'est assez? http://arduino.cc/en/Tutorial/DigitalPins

Et ben là je sait pas, le code du playground travaille avec des if en série = délais très court mais peu précis.
Mon code travail avec une boucle = délais plus long mais plus précis.
Pour mon code il faut une résistance de pull-up de 1Mohms minimum.

Pas simple tout ça!!!

Si la résistance passe de 1M à 20K, cela signifie que le condensateur se charge 50x plus vite.
Si je comprends bien, THRESHOLD doit passer de 50 à 1. J'ai testé mais pas de changements...

J'aurai préféré sans mais si je ne trouve pas de solution, j'utiliserai des résistances externes. Ce n'est pas bien grave.

Mon but est de réaliser une installation domotique avec des interrupteurs tactiles.
Si la carte arduino est dans une armoire électrique et qu'un fil part vers chaque interrupteur (le plus long fera +/- 20m)
Est-il possible d'avoir un fonctionnement correct sans perturbations? Du fil blindé ou un condensateur de filtrage pourrait suffire?

Qu'en pensez-vous?

Bonne soirée

tomt:
Si la carte arduino est dans une armoire électrique et qu'un fil part vers chaque interrupteur (le plus long fera +/- 20m)
Est-il possible d'avoir un fonctionnement correct sans perturbations? Du fil blindé ou un condensateur de filtrage pourrait suffire?

L'espoir fait vivre :grin:
J'arrive même pas à avoir des résultats "corrects" avec plus de 20cm de fils, alors 20m même blindé bonne chance !

Ce qu'il te faut c'est un vrai capteur capacitif avec sortie sur collecteur ouvert :
Exemple : http://www.lextronic.fr/P20494-capteur-sensitif.html

Salut,

Dommage, c'était trop simple pour être vrai... :slight_smile:

J'ai trouvé ce capteur à 4.6€ http://www.seeedstudio.com/wiki/index.php?title=Twig_-_Touch_Sensor
Peut-il convenir?
Connais tu un autre modèle qui serait encore moins cher? (sans le connecteur Grove)

Merci pour tes bons conseils.

Fut un temps il y avait le QT110, un capteur capacitif en boitier DIP-8 super simple à utiliser et pas chère.
Mais je crois qu'il n'est plus fabriqué :~

Sinon un équivalent en boitier cms c'est l'AT42QT1010 de ATMEL :