avril 24

Touche sensitive avec Teensy

Le Teensy permet de créer des touches dites sensitives (ou capacitives), cad qui détecte la présence, plus ou moins près selon le type de capteur et le réglages, d’une main ou d’un doigt.

Ce qui est cool, mais pas du tout indiqué sur leur site (qui est une horreur), c’est que selon les versions, des différences existes.

Avant la version 3

Avant la version 3, on devait utiliser une librairy à inclure au code et rajouter une résistance par entrée.

Le principe

Le corps humain peut être considéré comme un condensateur naturel, par rapport à la terre (masse). Avec une certaine valeur de résistance et une feuille d’aluminium au bout du fil, le capteur va commencer à sentir l’approche du doigt ou de la main

teensy-capacitive01

 

Le but du jeux consiste à connecter une résistance entre 2 borne du Teensy et de charger dans le code Arduino, la library CapSense (ou CapacitiveSensor). Cette dernière se charge de faire une boucle (while) de lecteur et test des pins.

A noter que l’on peut utiliser une seul pin Send avec plusieurs pin Receive, ce qui permet par exemple de n’utiliser que 4 pin pour faire 3 touches sensitives.

CapacitiveSensor mySensor(sendPin, reveicePin)
Crée l’objet CapacitiveSensor. En utilisant une paire spécifique de la broche. Vous devez créer un objet CapacitiveSensor distinct pour chaque capteur. Les capteurs peuvent partager le même sendPin, mais chaque besoin de ses propres reveicePin

mySensor.capacitiveSensor(numSamples)
Mesure le capteur. La mesure est répétée numSamples fois. Un grand nombre de mesures augmente la sensibilité, mais prend plus de temps de traitement.
Un temps écoulé, en unités arbitraires, est retourné. Un nombre négatif est retourné si une erreur survient.

La librairie contient aussi d’autres variables que je n’est pas encore exploré.

… »capacitiveSensor and capacitiveSensorRaw will return -2 if the methods timeout. This is caused by the count exceeding the value of CS_Timeout_Millis, which is set at a default value of 2000 milliseconds (2 seconds). This is most often caused by a missing resistor or the resistor in the wrong pin. It could also be caused by a sensor that is grounded or connected to +5 V…. …. »

La librairie va donc tester le nombre de fois ou la pin à détectée un doigt ou autre.
Au code alors de faire un test pour vérifier si la pin n’est pas activé par erreur (parasite, ondes…).
J’ai pas encore tout compris sur CS_Timeout_Millis mais il me semble que la boucle de test s’arrete au bout de 2 sec si il y a un problème de connectique ou branchement ???

Une broche étant considéré comme « émettrice » (send) et l’autre comme « réceptrice » (receive). La valeur de la résistance peut allez de 100 kΩ à 50 MΩ, selon le type de capteur (punaise, bout d’aluminium, fil…) et l’effet de proximité recherché :

  • Utilisez une résistance de 1 mégohm (ou moins peut-être) pour le toucher absolue pour l’activer.
  • Avec une résistance de 10 mégohm le capteur va commencer à répondre 4-6 centimètres.
  • Avec une résistance de 40 mégohm le capteur va commencer à répondre 12-24 centimètres (en fonction de la taille de la feuille).

Dans mon cas, j’ai utilisé des clous de tapissier en inox, reliés par un cable en nappe de 20cm et ça fonctionne bien.

Le code Arduino

En état, on peut afficher l’état on/off de la touche sensitive via le moniteur serie de de l’IDE Arduino (Ctrl+Maj+M) mais évidement la variable EtatBouton01 peut être utilisée pour déclencher des actions.

Avec 2 boutons

/*Testé sur Teensy 3.1*/

#include <CapacitiveSensor.h>

int TestBouton01;
int EtatBouton01;
int TestBouton02;
int EtatBouton02;
int TouchCommune = 14; // la pin "send"
int NBtestBoutons = 50; // nombres de test des boutons
int ValCapacitive = 2000; // valeur de l'entrée capacitive
CapacitiveSensor Bouton01 = CapacitiveSensor(TouchCommune,0); // une résistance de 1M entre les broches 14 et 1 = déclenchement en touchant du doigt la broche 0. 
CapacitiveSensor Bouton02 = CapacitiveSensor(TouchCommune,1); // une résistance de 1M entre les broches 14 et 2 = déclenchement en touchant du doigt la broche 1.

void setup() 
{
}

void loop() 
{
long TestBouton01 = Bouton01.capacitiveSensor(NBtestBoutons); // nombres de test du bouton
long TestBouton02 = Bouton02.capacitiveSensor(NBtestBoutons); // nombres de test du bouton
 if (TestBouton01 > ValCapacitive){ 
 EtatBouton01 = 1;
 Serial.print(" bouton 01 ");
 Serial.print("\n");
 delay(100);
 } 
 
 if (TestBouton02 > ValCapacitive){ 
 EtatBouton02 = 1;
 Serial.print(" bouton 02 "); // affiche 1e dans le moniteur serie
 Serial.print("\n");
 delay(100);
 } 
}

ValCapacitive est la valeur à partir de laquelle la touche est considéré comme déclenché.

NBtestBoutons est le nombre de fois ou la touche va être testé, grand = +précis mais +de ressource CPU utilisé.

Test

Pour définir la bonne valeur de déclenchement (ValCapacitive) au repos, il est souhaitable de faire un test qui affichera « ValCapacitive ». A noter, qu’au fil du temps, la valeur peut grossir. Donc, Si l’on voit qu’au bout 1/2 heure la valeur n’exede pas 1000 par exemple, on peut indiquer 1500 pour « ValCapacitive », histoire d’avoir un peux de marge.

Ce test permet aussi de tester l’isolation ou le blindage des fils reliant les boutons au Teensy, pour détecter d’éventuelle parasites.

Serial.print("BOUTON 01 : ");
Serial.print(TestBouton01);
Serial.print("\n");
Serial.print("BOUTON 02 : ");
Serial.print(TestBouton02);

Note

J’ai fait l’essais, en utilisant le même montage, de prendre une pin « Digital » et le résultat est le même ???.
Je n’ai pas plus creusé la question, 12 pin sensitive avec le Teensy 3.1 c’est déjà pas mal.

Améliorations

Un condensateur (100 pF – 0,01 uF) entre la masse et la pin du contact permet d’améliorer la stabilité du système.

Comme le système se sert de la terre pour fonctionner, un montage sur batterie (sans USB relié à un PC) aura peut être du mal. Dans ce cas, la solution être de placer près de la touche sensitive, une autre touche relié à la masse.

Il est conseillé aussi, pour l’utilisation de grande surface de touche, de placer sous les touches, une surface relié à la masse.

J’ai constaté aussi que le faite d’entourer les fils reliant les boutons avec un fil, ou un blindage, relié à la pin « receive » permet de faire baisser la valeur de « ValCapacitive »;

Anti-rebond

Dans beaucoup de système Arduino avec des boutons mécanique, on trouve des solutions pour éviter rebonds (debounce). Dans mes exmples, ça ne pose pas de soucis mais si vous voulez en rajouter une couche, vous pouvez allez voir ce tuto.

Sources

http://playground.arduino.cc/Main/CapacitiveSensor?from=Main.CapSense

https://www.pjrc.com/teensy/td_libs_CapacitiveSensor.html

A partir de la version 3

Avec la version 3 et 3.1, il n’est plus nécessaire d’inclure la librairy et de rajouter des résistances.

La lecture de la valeur (capacitive) de la pin se fait avec un simple : touchRead(numéro de pin);

Le principe reste le même que d’écris plus haut MAIS on peut supprimer une bonne partie du code.

Test de valeur capacitive moyenne au démarrage

Le système de touche capacitive dépendant de l’électricité ambiante, il peut être souhaitable de faire un test des touches AVANT de démarrer le programme.

J’ai rajouté aussi un système de tableau permettant de lire et d’attribuer, via une boucle for,  toutes les pins touchRead  du Teensy à autant de bouton (de 1 à 12).

/* Testé sur Tennsy 3.1 */
int calibrage = 4; // test X fois les boutons
int TestBouton[12];
int Bouton[12] = {1,2,3,4,5,6,7,8,9,10,11,12};
int PinBouton[12] = {0,1,15,16,17,18,19,22,23,25,32,33}; // PIN touchRead
int MaxTestBouton = TestBouton[0];
int SeuilBouton;

void setup()   {                
   Serial.begin(9600);
   pinMode(13, OUTPUT);
delay(1000);// si ça démarre au milieu d'un cycle   
//calibrage des pins boutons 
for (int i=1; i<=calibrage; i++)// lecture calibrage fois de chaque entrèes
{   
 for (int i=0; i<=11; i++)// lecture des 12 boutons  {      delay(100);// délai entre chaque test de bouton    TestBouton[i] = touchRead(PinBouton[i]);          Serial.print("Bouton ");         Serial.print(i+1);         Serial.print(" : ");         Serial.println(TestBouton[i]);          if (TestBouton[i] >MaxTestBouton)
{
  MaxTestBouton = TestBouton[i];
}
}
}           
SeuilBouton = MaxTestBouton+1000; // on ajoute une valeur significative
// au besoin, faire un test de valeur quand un bouton est touché
        Serial.println(" ");
        Serial.print("Valeur du bouton au repos : ");
        Serial.println(MaxTestBouton); 
        Serial.println(" ");
        Serial.print("Valeur de declenchement du bouton : ");
        Serial.println(SeuilBouton);
 
// a la fin du test, on fait clignoter la LED interne
digitalWrite(13, HIGH); 
delay(500);
digitalWrite(13, LOW);
}//setup

void loop(){ 
   
  for (int i=0; i<=11; i++)  {   Bouton[i] =  touchRead(PinBouton[i]);    }  if (Bouton[0] >= SeuilBouton)
{
  Serial.print("Bouton de la pin 0");
}
 
 }//loop

Test de valeur capacitive individuelle au démarrage

Si l’on a des boutons sensitives avec des valeurs au repos différentes (c’était mon cas même avec des boutons proches et sur un même support), un test qui renvoie une valeur de la plus élevé n’est pas bine conseillé.

J’ai fais un autre système permettant de tester (1 seul fois par contre) la valeur de tous les boutons et donc d’avoir une valeur de seuil (qui met sur ON) propre à chaque boutons.

int TestBouton[12]; // au démarrage
int Bouton[12] = {1,2,3,4,5,6,7,8,9,10,11,12};
int IntervalTestBouton = 200; // temps entre le test de chaques bouton
boolean EtatBouton[12]; // bouton touché ou au repos
int PinBouton[12] = {0,1,15,16,17,18,19,22,23,32,33,25}; // PIN touchRead
int ValeurSeuilBouton = 500; // ajout à la valeur testé au démarrage
int SeuilBouton[12]; // valeur ou les boutons sont considérés ON

void setup() {

//calibrage des pins boutons   
 for (int i=0; i<=11; i++)// lecture des 12 boutons
 {  
   delay(IntervalTestBouton);// délai entre chaque test de bouton
   TestBouton[i] = touchRead(PinBouton[i]); 
  SeuilBouton[i] = TestBouton[i]+ValeurSeuilBouton;
  
        Serial.println(" ");
        Serial.print("Valeur du bouton au repos : ");
        Serial.println(TestBouton[i]); 
        Serial.println(" ");
        Serial.print("Valeur de declenchement du bouton : ");
        Serial.println(SeuilBouton[i]);
}
}//setup

void loop() {
  
  /* BOUTONS SENSITIFS */  
  for (int i=0; i<=11; i++)
 {
  Bouton[i] =  touchRead(PinBouton[i]);

      if (touchRead(PinBouton[i]) > SeuilBouton[i])
      {
       EtatBouton[i] = true; 
       //Serial.println(EtatBouton[i]); 
      } 
      else
      {
        EtatBouton[i] = false;
       } 
  }

// on fait ce que'on veut
if (EtatBouton[0])
  {
// son code içi
  }



}//loop

Ajout d’un anti-rebond

Si l’on souhaites prémunir les touches des rebonds, ce qui peut être problématique si on envoie des données séries par exemple, j’ai rajouté un système qui détermine un temps minimum de déclenchement entre 2 touche du bouton.

A rajouter avant le setup

elapsedMillis  TempsBouton = 0;
int RebondBouton = 200; //  X milli-seconds minimum entres chaque touche de bouton

Et une petite modification du code de la loop

  /* BOUTONS SENSITIFS */
  for (int i=0; i<=11; i++)
 {
  Bouton[i] =  touchRead(PinBouton[i]);

      if (touchRead(PinBouton[i]) > SeuilBouton[i] && TempsBouton >= RebondBouton)
      {
TempsBouton = 0;
EtatBouton[i] = true; 
//Serial.println(EtatBouton[i]); 
      } 
      else
      {
        EtatBouton[i] = false;
      }        
  }

**

Infos

Créer un slider sensitif


Étiquettes : ,
Copyright 2017. All rights reserved.

Ecrit 24 avril 2015 par Pit dans la catégorie "Teensy/Arduino

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.

4 + 2 =