juillet 30

Récupérer la valeur MIDI du volume

Un croquis permettant de récupérer la valeur MIDI du curseur de volume de Ableton Live et de l’envoyer, via USB/MIDI, sur un Teensy 3.

A noter que, à chaque changement de set Live, la valeur du volume est automatiquement envoyé !

void setup()
{

}

void loop()
{
int ControleChange, valeur;
  if (usbMIDI.read()) 
  {      // si il y a des messages MIDI
      int ControleChange = usbMIDI.getData1();
      int valeur = usbMIDI.getData2();
    Serial.print("Control change: ");
    Serial.println(ControleChange);   
    Serial.print("Valeur: ");
    Serial.println(valeur);
  }

}//loop
Catégorie : Teensy/Arduino | Commenter
février 27

Clignotement SANS delay()

Sous Arduino ou Teensy, le clignotement d’une LED avec la commande delay() ralentit tout le code.

1 – Avec la fonction elapsedMillis

Heureusement, la fonction elapsedMillis, qui génère un compteur permet de se passer de delay.
J’ai concocté une fonction qui permet d’allumer et d’éteindre une LED x sec toute les x sec.

int LEDcligno = 20; // LED entre pin 20 et la masse, via résistance
int EtatLEDcligno = HIGH;
int ChangeLEDcligno = 0;
elapsedMillis ComptCligno; //compteur

void setup()
{
pinMode(20, OUTPUT); 
}
void loop()
{
ClignoLED(250, 15000); // 1/4 sec, 15 sec
}//loop

void ClignoLED (int on, int off)
{
int intervalle = ComptCligno - ChangeLEDcligno;
if (EtatLEDcligno == HIGH && intervalle > on)
{
    // éteint 
    EtatLEDcligno = LOW;
    digitalWrite(LEDcligno, EtatLEDcligno);
    ChangeLEDcligno = ComptCligno;
}
  else if (EtatLEDcligno == LOW && intervalle > off) 
  {
    // allumé
    EtatLEDcligno = HIGH;
    digitalWrite(LEDcligno, EtatLEDcligno);
    ChangeLEDcligno = ComptCligno;
  }
intervalle = 0;//RAZ
}//void

2 – Avec le cycle d’horloge

Les instructions du Teensy sont exécutés en boucle, à une fréquence de 96Mhz. Entre le début et la fin de la boucle, il se passe donc un certains temps, dépendant principalement du nombre d’instructions que le teensy doit effectuer.

int ComptLED = 1;
int TempsON = 14000;

void setup() {
  pinMode(2, OUTPUT);//LED
  digitalWrite(2, LOW);// démarrer éteint 
  pinMode(4, INPUT_PULLUP);//contact

}

void loop() {
ComptLED = ComptLED+1;
 Serial.println(ComptLED); 
if (digitalRead(4) == LOW)// si contact
{
 digitalWrite(2, HIGH);// allumer la LED
}

if (ComptLED == TempsON)// au bout d'un certains temps
{
  digitalWrite(2, LOW);// éteindre la LED  
   ComptLED = 1;  
}
}//loop

C’est moins précis car il faut ajuster « ComptLED » à la mano mais ça fonctionne.

Catégorie : Teensy/Arduino | Commenter
juillet 19

Envoyer plusieurs données entre Teensy et Xbee

J’avais déjà indiqué comment envoyer une donnée à la fois (en faite un byte à la fois) pour commander en ON/OFF une LED par exemple MAIS si l’on souhaite envoyer plusieurs données en série du style :  Si j’envoie la lettre A alors les 3 données suivantes concerne le groupe A,  ça se complique.

J’ai essayé via la library fournis par Xbee mais je n’arrive à rien !

Le code émetteur

/* testé sur Teensy 3.1 et Xbee série 1.
#define HWSERIAL Serial2 //TX2 pin10


void setup() {/********************** SETUP *****************************/
  HWSERIAL.begin(9600);
}

void loop() {
  
  HWSERIAL.write('a');
  HWSERIAL.write(1);
  HWSERIAL.write(2);
  HWSERIAL.write(3);
  delay(1000);
  
   HWSERIAL.write('b');
  HWSERIAL.write(10);
  HWSERIAL.write(20);
  HWSERIAL.write(30);
  delay(1000);
}//loop

Le code récepteur

/* testé sur Teensy 3.1 
on envoie via serie un write(a ou b), si il est reçu, on reçoit les 3 données suivantes.
*/
#define HWSERIAL Serial1

byte DataSerie[4];
byte InSerie;

void setup(){
   HWSERIAL.begin(9600);
 
}


void loop(){
 while (HWSERIAL.available())
{// on place les 4 bytes reçu dans un tableau

      for (int i=0; i<=3; i++)
      {
byte InSerie = HWSERIAL.read();  
DataSerie[i] = InSerie;
      }//for
if (DataSerie[0] == 'a')// le premier byte envoyé doit être le caractère a 
{
 Serial.println("bien recu a"); 
 Serial.println(byte(DataSerie[1]));
  Serial.println(byte(DataSerie[2]));
   Serial.println(byte(DataSerie[3]));
}
if (DataSerie[0] == 'b')
{
 Serial.println("bien recu b"); 
 Serial.println(byte(DataSerie[1]));
  Serial.println(byte(DataSerie[2]));
   Serial.println(byte(DataSerie[3]));  
}
}//while
}//loop

J’ai délibérément fait simple mais c’est une base pour faire des trucs sympa !

Autre façon de faire

Catégorie : Teensy/Arduino | Commenter
juillet 13

Fonction pour afficher dans le moniteur serie

Il n’est parfois pas facile, vu la vitesse de défilement du moniteur série d’Arduino, de voir la valeur d’une variable.

Placer l’appel de la fonction :

MoniteurSerie(String("Valeur du volume"), ValeurVolume);

Et après le LOOP, la fonction.
Il suffira juste de jouer sur le delay pour ralentir l’affiche de tous les appels à la fonction.

void MoniteurSerie(String texte, int variable)
{
  Serial.print(texte);
  Serial.print(": ");
  Serial.print(variable);
  Serial.println("");
  delay(10); 
}

 

Catégorie : Teensy/Arduino | Commenter
juillet 13

Modification de variable via une liaison série

J’ai fais un montage avec Teensy et Xee permettant à 1 bouton de dire via une liaison série :  si je suis appuyé, la variable MaVariable = 1, sinon MaVariable = 0.

J’ai donc : appuie bouton = envoie série de « on », si pas d’appuie = envoie série de « off ». Problème, au repos, j’envoie sans arret le code « off » ce qui est pas top en terme de gestion de l’énergie.

Je pourrais faire, sur la partie réception : si j’envoie autre chose que « on », alors on considère que c’est « off ».
Le truc est que en même temps, j’envoie d’autres code en série, donc cette solution ne tient pas.

J’ai trouvé l’astuce en jouant sur un compteur.

Si le bouton sur OFF, je compte jusqu’à 3 MAIS SEULEMENT à 2, j’envoie le code série « off ». Le compteur reste bloqué à 3 (donc plus d’envoie série) jusqu’à que je bouton soit « on », quand i l’est, l’incrément du compteur se remet sur 1 et attend donc que le bouton soit « off » pour recompter.

Je ne mat pas le code qui fait : si tu appuie, fait : HWSERIAL.write(« on »);

if(Bouton == 1) // si le bouton est ON, on met le compteur = 1
{
  ComptBouton = 1;
  }
if (Bouton == 0 && ComptBouton <=3)//quand le bouton est OFF, on compte jusqu'à 3
{
for (ComptBouton = 1; ComptBouton <=3; ComptBouton++)
{
if(ComptBouton == 2)// à 2, on envoie le code off
{
HWSERIAL.write("off"); 
}//if
}//for
}//if bouton

Comme j’ai galéré un moment sur ça, je partage !

Catégorie : Teensy/Arduino | Commenter
juillet 9

Volume MIDI via liaison série

Le Teensy 3.1 est reconnu nativement comme un périphérique compatible MIDI et il permet aussi de créer des touches à effleurement (capacitive).
Le Xbee (serie 1) est très simple à configurer, voila de quoi faire une belle télécommande audio.

Code émetteur

/* testé sur Teensy 3.1 :
Un les touches à effleurement incrémentent ou décrémentent une valeur de volume (0 à 127).
Un appuie sur une des deux touches envoie via serie, la lettre 'v' qui indique au récepteur que l'on envoie une valeur de volume.
Ensuite, on evoie la valeur de volume. */

#define HWSERIAL Serial2 //TX2 - pin 8
#include <CapacitiveSensor.h>

/*VOLUME*/
int TestBouton10;
int EtatBouton10;
int TestBouton11;
int EtatBouton11;
int ValeurVolume;
/* au changement de set Ableton, à la 1er impulsion des boutons, le volume se met une fraction de seconde au volume du set précédent (ComptVolume part de la dernière valeur) */
const int latenceVolume = 10; // vitesse du curseur
const int MaxHaut = 127; //127 en MIDI

/* TOUCHE SENSITIVE */
int BoutonCommun = 14; // pin commune
int NBtestBoutons = 30; // nombres de test des boutons
int ValCapacitive = 2000; // valeur de l'entrée capacitive

//VOLUME
CapacitiveSensor   Bouton10 = CapacitiveSensor(BoutonCommun, 32); // Volume + (pin 32)
CapacitiveSensor   Bouton11 = CapacitiveSensor(BoutonCommun, 33); // Volume - (pin 33)

void setup() {/********************** SETUP *****************************/
  HWSERIAL.begin(9600); 
}

void loop() {

  //VOLUME
  long TestBouton10 =  Bouton10.capacitiveSensor(NBtestBoutons);
  long TestBouton11 =  Bouton11.capacitiveSensor(NBtestBoutons);

   /**************************************************************** ENVOIE SERIE - VOLUME */
  if (TestBouton10 > ValCapacitive && ValeurVolume < MaxHaut)
  {
       HWSERIAL.write('v');
        ValeurVolume++;
HWSERIAL.write(ValeurVolume);
    delay(latenceVolume);
  }

  if (TestBouton11 > ValCapacitive && ValeurVolume > 0)
  {    
   HWSERIAL.write('v'); 
      ValeurVolume--;
HWSERIAL.write(ValeurVolume);
    delay(latenceVolume);
  }
Serial.println(ValeurVolume);
}//loop

Code récepteur

/* testé sur Teensy 3.1 
on envoie via serie un write('v') et ensuite un write avec une valeur numérique.
si le a est reçu, alors on affiche la valeur numérisue.
*/
#define HWSERIAL Serial1

byte DataSerie[1]; //tableau de 2 valeurs (0 et 1)
byte InSerie;
int i;

void setup(){
   HWSERIAL.begin(9600);
 
}


void loop(){
 while (HWSERIAL.available())
{// on place les 2 byte recu dans un tableau
i = 0;
      for (i=0; i<=2; i++)
      {
byte InSerie = HWSERIAL.read();  
DataSerie[i] = InSerie;

if (char(DataSerie[0]) == 'v')// le premier byte envoyé doit être le caractère v 
{
 Serial.println("bien recu v"); 
 int ValeurVolume = byte(DataSerie[1]);
 usbMIDI.sendControlChange(12, ValeurVolume, 1); //ProgramChange 12, canal MIDI 1
 Serial.println(ValeurVolume );
}
      }//for
      i = 0;
}//while
 
          }//loop



Limitation

Si on envoie d’autre données série en même temps, cela perturbe  le système, les autres données s’intercalant entre la lettre déclencheur ‘v’ et la valeur du volume.
L’idéal serait d’envoyer une seule donnée du style V+ValeurVolume et de découper ensuite en 2 dans la partie récepteur.

 

Catégorie : Teensy/Arduino | Commenter
juin 8

Envoyer une donnée entre Teensy et Xbee

Le pitch étant d’envoyer une phrase, ou une variable, entre 2 Teensy 3.1, relié chacun à un Xbee serie 1.

La connexion

  • 1 = 3.3 Volt –> vers pin 3.3 Volts du Teensy
  • 2 = Digital OUT —> vers pin 0 (RX1) du Teensy
  • 3 = Digital IN —> vers pin 1 (TX1) du Teensy
  • 10 = GND –> vers pin GND du Teensy

xbee-pins teensy31_front_pinout

 

Pour ma part, je n’ai pas eu besoin de programmer quoi que ce soit sur les Xbee.
J’ai un couple Teensy/Xbee sur mon PC fixe et un autre couple sur mon portable.

La programmation

J’ai vu beaucoup d’exemples divers de sketch Arduino ou Teensy, vers comme souvent, les gens n’indique pas la version de leur matos. Donc, j’ai fais ma petite sauce, qui fonctionne sur Teensy 3.1.

Envoie

/* Testé sur Teensy 3.1 */ 
#define HWSERIAL Serial1 // pin 0 et 1
void setup() {
HWSERIAL.begin(9600);
}
void loop() {
HWSERIAL.println("Hello"); //ln pour avoir un retour à la ligne après "hello"
delay(500);
}

Réception

/* Testé sur Teensy 3.1 et Xbee serie 1 */
#define HWSERIAL Serial1

void setup() {
HWSERIAL.begin(9600);
}
 
void loop() {
if (HWSERIAL.available())// si des données sont présentes
{
Serial.print(char(HWSERIAL.read())); // char ) caractère, rien ou int = code ASCII
} 
}//loop

 

Dans la console moniteur serie du récepteur, on récupère le mot ou la phrase envoyé.

OK mais le top c’est que ça serve à quelque chose. On va donc tacher d’envoyer une variable précise qui va déclencher l’allumage de la LED interne du Teensy.

/* Testé sur Teensy 3.1 et Xbee serie 1.
Xbee sur pin 0 et 1 du Teensy */
#define HWSERIAL Serial1
byte InSerie;

void setup() {
HWSERIAL.begin(9600);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
 
void loop() {

if (HWSERIAL.available())
{
byte InSerie = HWSERIAL.read();
Serial.println(InSerie);
if (InSerie == 'A')
{
Serial.print("recu");// pour vérification
digitalWrite(13, HIGH);
}
else
{
digitalWrite(13, LOW);  
}
}
}//loop

Amélioration

La fonction Print est plus dédié à l’affichage dans une console ou un afficheur LCD, lisible pour un humain.

Dans mon cas, je souhaite envoyer des valeurs, parfois sur plusieurs chiffres. dans ce cas, la fonction write et byte est préférable.

Envoie

#define HWSERIAL Serial1

void setup() {
HWSERIAL.begin(9600); 
}

void loop() {
HWSERIAL.write(1);
delay(1000);
HWSERIAL.write(0);
delay(1000);
}//loop

Réception

#define HWSERIAL Serial1
byte InSerie;

void setup() {
HWSERIAL.begin(9600);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
 
void loop() {

if (HWSERIAL.available()>0)
{
InSerie = HWSERIAL.read();
Serial.println(byte(InSerie) );
if (InSerie == 1)
{
digitalWrite(13, HIGH);
}
if (InSerie == 0)
{
digitalWrite(13, LOW); 
}
}
}//loop

La pour le coup, on peut commencer à vraiment commander des trucs entre les 2 teensy.

Notes sur la liaison série

Le protocole série n’envoie par des lettres et/ou des symboles mais des nombres, du code  binaire, hexadécimal… qui sont en correspondance.

Selon ce tableau, faire un Serial.write(‘a’); et Serial.write(97);  (97 en décimal = ‘a’) enverra le même code. On ne peux pas dire au Teensy de faire : si tu reçois ‘a’, fait ça et si tu reçois 97 fait ça; L’action sera la même.

Catégorie : Teensy/Arduino | Commenter
mai 24

Les modules Xbee

Présentation

Ce sont des petits modules électroniques, compatible Arduino et Teensy, permettant d’envoyer des données « serie » sans-fil.
Il y a malheureusement plusieurs types de modules (serie 1, serie 2, XeeBee, Znet) créant je trouve une grande confusion.
La serie 1 est aussi appelé 802.15.4 et la serie 2 ZB ou ZigBee.

A priori, avec la serie 1 c’est automatique, les Xbbe communiquent même sans passer par la case programmation.
Pour les serie 2, vu les différents « mode » disponible, la programmation est indispensable.

Pour ma part, j’ai eu des résultats très « chaotiques », je déconseille donc l’utilisation de la serie 2, du moins pour un projet simple de envoie/réception de donnée.

(difference entre serie 1 et 2)

xbee-comparaisons

  • les modules des séries 1 et 2 ne sont pas compatibles entre eux ;
  • la portée et la consommation sont sensiblement les mêmes ;
  • le nombre d’entrées et sorties est différent et surtout la série 2 ne possède pas de sorties analogiques PWM ;
  • les topologies de réseaux possibles ne sont pas les mêmes :
    • Avec la série 1, l’architecture est simple : point à point (pair) ou multipoint (star).
    • La série 2 permet en plus de créer des réseaux plus complexes : maillés (mesh) ou en « arbre » (cluster tree).

xbee-reseaux

 

Hardware

De plus, différente version hardware existe aussi (antenne intégrée, connecteur antenne, antenne extérieur…)

xbee-antenne

 

  • wire :  min antenne omnidirectionnelle
  • chip : antenne intégrée, sous forme de puce (le signal est atténué dans certaines directions) ;
  • U.FL : antenne intégrée ( à vérifier) et une mini prise pour une antenne externe
  • RPSMA : plus gros que le connecteur U.FL, permet de placer son antenne à l’extérieur d’un boîtier.

Même le logiciel (Xctu) servant à programmer les modules à changé de version et de look… difficile donc de si retrouver avec les nombreux tutos présents sur le net, comme souvent qui ne précise pas avec quelle version de ce *** de Xbee il font leur tuto.

Le brochage des pins est le même entre la serie 1 et la serie 2

xbee-pins

Chaque XBee dispose d’une adresse 64 bits imprimé sur le dos.
Le début ou la partie « HIGH » de l’adresse seront 0013A200 (pré-attribué pour Digi). La dernière partie ou «LOW» de l’adresse sera différent pour chaque Xbee. Notez ces chiffres, ça peut servir pour la suite.

xbee-etiquette

 

Connexion

L’écarts des pins du Xbee n’est pas au pas standard (veroboard, breadboard…)
Il faut donc passer par des interface (Arduino ou USB) pour tester la bête.

Xbee-pin-board xbee-usb-board

 

Configuration

L’interface USB SparkFun, permet de le brancher directement sur un PC, afin qu’il soit reconnu par le logiciel dédié à sa configuration (voir plus bas).

xbee-usb-pc

Cette interface dispose d’un bouton permettant faire un « reset » du Xbee, en cas de problème de mise à jour par exemple.
Ce bouton fait juste un court-circuit entre la broche 5 et la broche 10 (gnd).

La connexion vers Arduino ou autre est des plus simple :

  • 1 = 3.3 Volt (pas de 5 Volt)
  • 2 = Digital OUT —> vers RX arduino (receive)
  • 3 = Digital IN —> vers TX arduino (transmitte)
  • 10 = GND

Avec Teensy 3.1, on peut utiliser un sketch permettant de faire un « pont » entre les données « serie » et le port USB.
Ce système permet d’utiliser la prise USB du Teensy pour le programmer mais surtout, de le faire reconnaître par le logiciel X-CTU, pour sa configuration.

Il suffit de connecter le Xbee au Teensy (parmis les 3 ports série disponible), de charger le sketch : Fichier/exemples/Teensy/USB_Serial/USBtoSerial, de mettre Teensy en mode serie : Outils/USB type = Serial. Une fois le teensy connecté en USB au PC, X-CTU devrait le voir.

Attention : bien prendre note de la vitesse serie indiqué dans le sketch lors de la recherche du Xbbe par X-CTU.

Programmation

La programmation des Xbee se fait via  un logiciel dédié, à savoir X-CTU.

Les modes

AT = Transparent

C’est le mode par défaut, le plus simple à configurer

API = Application Programming Interface

« …envoyer et recevoir des données vers et à partir de série UART de la radio. L’API est une alternative au mode transparent par défaut. L’API permet au programmeur la possibilité de: Modifier les paramètres sans passer en mode de commande (XBee seulement) Voir RSSI et l’adresse de la source sur un paquet par base de paquets Recevez la confirmation de livraison de paquets sur chaque paquet transmis… »

Le mode API n’est possible qu’avec une connexion locale en série et filaire avec l’ordinateur et Arduino, pas entre modules XBee.

COMMAND

Il permet de configurer le module : ses entrées, ses sorties, son adresse, l’adresse de destination de ses messages, etc.

Ouvrez le terminal choisi. Avant tout, il faut signaler au XBee que l’on veut quitter le mode TRANSPARENT pour entrer dans le mode COMMAND. Pour cela il faut prendre le coup de main, suivez bien ces instructions à la lettre :

  • Taper +++ et attendre 1 seconde sans appuyer sur aucune autre touche, le message OK devrait alors s’afficher comme sur l’image du terminal.
    Par ce OK, le XBee nous signale qu’il passe en mode COMMAND et qu’il est prêt à recevoir les messages de configuration.
  • Si vous attendez plus de 10 secondes sans appuyer sur une touche, le XBee revient en mode TRANSPARENT. V
    ous devez alors retaper +++ pour revenir en mode COMMAND.

Dans les télécommunications, l’ensemble de commandes Hayes est un langage de commandes spécifiques développé pour le modem Hayes SmartModem 300 en 1981. Les commandes sont une série de mots courts qui permettent de contrôler le modem avec un langage simple (composer un numéro de téléphone, connaître l’état de la ligne, régler le volume sonore…) Ce jeu de commandes s’est ensuite retrouvé dans tous les modems produits
(sources :http://fr.wikipedia.org/wiki/Commandes_Hayes , http://en.wikipedia.org/wiki/Hayes_command_set ).

Pour avoir un aperçu rapide des commandes disponibles pour le XBee, télécharger le guide de référence des commandes AT de Sparkfun .

Sources:

http://www.pobot.org/-Reseaux-ZigBee-.html

http://jeromeabel.net/ressources/xbee-arduino

https://docs.digi.com/display/XCTU/Configure+your+modules

Catégorie : Teensy/Arduino | Commenter
mai 14

Bontons Up/Down controller MIDI

Le pitch étant de contrôler le volume MIDI générale de Ableton Live avec 2 boutons poussoirs (ou un interrupteur 2 positions), le commun étant relié à la masse..
Dans mon test, en mettant la valeur 7 (CC MIDI) pour controler le curseur j’ai des « sautes » rapide du curseur ??!!, j’ai donc mis la valeur 12 (effect control) en tant que controller du curseur de volume et ça marche à merveille !

Tous les codes MIDI içi

/* testé sur teensy 3.1 */
/* au changement de set Ableton, à la 1er impulsion des boutons, le volume se met une fraction de seconde au volume du set précédent (Compteur part de la dernière valeur) */

/* TYPE DE MESSAGE MIDI :
0 = Bank select
1 = modulation
2 = Breath control
3 = non défini
4 = Foot controller
5 = portamento
6 = données MSB
7 = Volume
8 = balance
9 = non défini
10 = panoramique
11 = expression controller
12 = effect control 1
13 = effect control 2
14/15 = non défini
*/

int TypeMessage = 12;
int MIDIchannel = 1;
const int Latence = 10; // vitesse du changement
const int MaxHaut = 107; //de 0 à 127 en MIDI. 107 = 0 dB
const int BoutonBas = 32; //pin
const int BoutonHaut = 33;//pin
int EtatBoutonBas;
int EtatBoutonHaut;
int Compteur = 107; //pour démarrer 0 dB

void setup() {
  /* boutons */
  pinMode(BoutonBas, INPUT_PULLUP);
  pinMode(BoutonHaut, INPUT_PULLUP);
}

void loop() {

  EtatBoutonBas = digitalRead(BoutonBas);
  EtatBoutonHaut = digitalRead(BoutonHaut);

  if (EtatBoutonBas == LOW && Compteur < MaxHaut)   {       usbMIDI.sendControlChange(TypeMessage, Compteur, MIDIchannel);       Compteur++;       delay(Latence);   }   if (EtatBoutonHaut == LOW && Compteur > 0)
  {
      usbMIDI.sendControlChange(TypeMessage, Compteur, MIDIchannel);
      Compteur--;
      delay(Latence);
  }
}//loop
Catégorie : Teensy/Arduino | Commenter
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

Catégorie : Teensy/Arduino | Commenter