Accueil / Arduino / Tutoriels Arduino / Réaliser un encodeur optique angulaire à l’aide de phototransistors

Réaliser un encodeur optique angulaire à l’aide de phototransistors

Pour réaliser la girouette du projet d’anémomètre avec girouette connectés à base d’ESP8266, j’ai cherché une solution simple et peu couteuse pour déterminer la direction du vent. En faisant mes recherches, j’ai trouvé comment réaliser un encodeur de position angulaire absolue à base de Led et des phototransistors. Je vous propose de découvrir le principe de fonctionnement de ce capteur dans ce tutoriel. Vous y trouverez peut être d’autres applications dans vos projets diy. J’imagine qu’en robotique ce type d’encodeur pourrait être très utilise.

Cet encodeur remplacera également avantageusement un potentiomètre angulaire à 360° (lire le tutoriel sur le Keyes KY-040) qui ne permet d’encoder que des positions relatives.

Phototransistor Vishay TEPT4400

L’idée est donc d’utiliser des phototransistor pour réaliser l’encodeur optique. Un phototransistor fonctionne comme un interrupteur qui passe à l’état bas (LOW) en présence de lumière. J’ai trouvé des Vishay TEPT400 vendus par lot de 5 pour environ 4,50€ sur eBay ou Aliexpress mais vous pouvez également utiliser des Osram SFH310 (ou 310) qui sont toutefois beaucoup plus chers (documentation technique).

Comme pour chaque détecteur, le phototransistor présente des avantages et des inconvénients.

Pour commencer, voici les principaux avantages :

  • Le phototransistor est très similaire à une led (blanche) et compacte (3mm de diamètre avec 2 broches). Le branchement est similaire.
  • Le spectre de détection est très large ce qui permet de choisir presque n’importe quelle couleur de Led (figure ci-dessous).
  • Le prix est raisonnable.

Mais il y a aussi quelques inconvénients :

  • Comme une Led, le phototransistor nécessite une résistance en amont pour fonctionner.
  • La détection est directionnelle (30°). La Led devra être dans l’axe du phototransistor pour avoir une bonne détection.
  • La distance de détection est proportionnelle à la puissance lumineuse. Elle est assez faible, entre 10 et 15mm. Les Leds devront être alimentées à pleine puissance pour que l’encodeur de position fonctionne bien.

Ce phototransistor peut être alimenté directement en 5 Volts depuis la carte Arduino (un ESP8266 ou un Raspberry Pi). Il est sensible de 440 à 800nm avec un maximum à 570nm, ce qui correspond à la couleur jaune. Cependant, son spectre de détection est assez large (dans le cas du Vishay TEPT4400) ce qui permet de choisir une autre couleur (rouge, vert, bleu) sans affecter significativement son fonctionnement. La documentation technique est disponible ici pour tout savoir sur ses caractéristiques.

Sensibilité spectrale du phototransistor Vishay TETP4400. Max. à 570nm
Sensibilité spectrale du phototransistor Vishay TEPT4400. Sensibilité maximale à 570nm.

Comment réaliser un encodeur optique à base de code de Gray ?

Pour réaliser de détecteur, je me suis appuyé sur cet article publié en 2013 par Yoctopuce (un fabricant Suisse de cartes d’acquisition, d’actionneurs, et capteurs). Sans rentrer trop dans les détails techniques, on place un disque d’encodage entre les Led et les phototransistors. Les Led sont placées sur un cercle.

Remarque. J’ai utilisé Autodesk Fusion 360 pour la CAO. Tous les fichiers se trouvent sur le github ici.

Maintenant on va découper dans ce disque des lumières de manière à ce qu’à chaque changement de position (incrément du capteur), il n’y ait que l’état d’un seul phototransistor qui change. Pour cela, on créé 32 cercles (ce qui donne une meilleure précision de mesure qu’avec 30).

Encodeur optique préparation découpe lumières

Il ne reste plus qu’à supprimer les disques et les arc inutiles en utilisant l’outil « Break« . Voici la séquence que j’ai découpé :

  • La plus grande lumière est composée de 10 cercles.
  • Ensuite on laisse 4 cercles vides
  • La seconde lumière est composée de 3 cercles
  • Ensuite on laisse 2 cercles vides
  • Et enfin la troisième lumière est constituée par 2 cercles

encodeur optique lumière disque encodage vishay tetp4400 phototransistor

Amélioration. Ce capteur est encore au stade du prototype. Si vous l’avez amélioré, n’hésitez pas à partager vos améliorations dans les commentaires avec la communauté.

Circuit et matériel nécessaire

Pour réaliser votre encodeur de position optique vous aurez besoin du matériel suivant :

Voici le circuit à réaliser sur une breadboard.

circuit encodeur optique tept4400 vishay

Code

Le code du capteur est vraiment très simple. Le code de Gray permet de ne pas avoir d’état transitoire lors d’un changement d’état du capteur. Ce n’est pas un problème pour projet DIY Arduino mais ce n’est pas le cas pour un capteur industriel qui doit mesurer avec précision des mouvements rapides (en robotique par exemple). Ici c’est le principe qui compte avant tout.

On a donc besoin de 5 entrées numériques. La fonction getPosition() va lire l’état de chaque bit et prendre son opposé. Il ne reste plus qu’à convertir en byte pour obtenir un index de position. Pour cela il suffit d’attribuer un poids à chaque bit. Par exemple pour 10110, on fait 0*1 + 1*2 + 1*4 + 0*8 + 1*16 = 0+2+4+0+16 = 22.

/*
 * Encodeur angulaire optique à base de phototransistor (code de Gray)
 *   
 * http://www.projetsdiy.fr - Juin 2016 - Version 1.0
 * Licence : MIT
 * 
  */

volatile int rpmcount = 0;
int rpm = 0;
unsigned long lastmillis = 0;
bool debug = false;

//
int pinBit0 = 7;
int pinBit1 = 8;
int pinBit2 = 9;
int pinBit3 = 10;
int pinBit4 = 11;

int bit0 = 0;
int bit1 = 0;
int bit2 = 0;
int bit3 = 0;
int bit4 = 0;

byte _position = 0;

void setup() {
  Serial.begin(9600);
  pinMode(pinBit0, INPUT);
  pinMode(pinBit1, INPUT);
  pinMode(pinBit2, INPUT);
  pinMode(pinBit3, INPUT);
  pinMode(pinBit4, INPUT);
}

void loop() { 
  getPosition();
  delay(2000);
}


void getPosition(){
  bit0 = not(digitalRead(pinBit0));
  bit1 = not(digitalRead(pinBit1));
  bit2 = not(digitalRead(pinBit2));
  bit3 = not(digitalRead(pinBit3));
  bit4 = not(digitalRead(pinBit4));
  
  _position =  (bit4 * 16) + (bit3 * 8) + (bit2 * 4) + (bit1 * 2) + bit0;

  Serial.print(bit0); Serial.print(bit1); Serial.print(bit2); Serial.print(bit3); Serial.print(bit4);
  Serial.print(" => ");
  Serial.print(_position);
}

Réalisation des éléments par impression 3D et assemblage

Vous pouvez récupérer et imprimer les fichiers STL de la girouette dur le projet github ici. Vous devez imprimer au moins les pièces suivantes :

  • Boitier girouette (83 minutes, 27g de PLA)
  • Disque encodeur (13 minutes, 3g de PLA)
  • Support Led (33 minutes, 9g de PLA)
  • fabriquer un support pour les phototransistor ou imprimer la plaque de liaison (67 minutes, 21g de PLA)

Une fois les éléments fabriqués par impression 3D, suivez les étapes d’assemblage du projet d’anémomètre et girouette connectés.

Une fois assemblé, vous obtiendrez ceci.

2. Girouette assemblée

Index des positions en images

Le tableau ci-dessous illustre le fonctionnement du capteur. Pour bien montrer le fonctionnement du code de Gray, j’ai mis en gras le bit qui à changé d’état entre deux changement d’orientation. En attribuant un poids à chaque bit (1 pour le bit0, 2 pour le bit1…), on obtient facilement l’index de la position.

Incrément Direction du vent

(rotation du disque codeur)

Index de position bit4

Poids : 16

bit3

Poids : 8

bit2

Poids : 4

bit1

Poids : 2

bit0

Poids : 1

1 Code de gray 1 0 0 0 0 1
2 2- 00011 3 0 0 0 1 1
3 3- 01011 11 0 1 0 1 1
4 4- 11011 27 1 1 0 1 1
5 5- 10011 19 1 0 0 1 1
6 6- 10010 18 1 0 0 1 0
7 7- 00010 2 0 0 0 1 0
8 8- 00110 6 0 0 1 1 0
9 9- 10110 22 1 0 1 1 0
10 10- 10111 23 1 0 1 1 1
11 11- 00111 7 0 0 1 1 1
12 12- 00101 5 0 0 1 0 1
13 13- 00100 4 0 0 1 0 0
14 14- 01100 12 0 1 1 0 0
15 15- 01101 13 0 1 1 0 1
16 16- 01111 15 0 1 1 1 1
17 17- 01110 14 0 1 1 1 0
18 18- 01010 10 0 1 0 1 0
19 19-01000 8 0 1 0 0 0
20 20- 11000 24 1 1 0 0 0
21 21- 11010 26 1 1 0 1 0
22 22- 11110 30 1 1 1 1 0
23 23-11100 28 1 1 1 0 0
24 24- 10100 20 1 0 1 0 0
25 25- 10000 16 1 0 0 0 0
26 26- 10001 17 1 0 0 0 1
27 27- 10101 21 1 0 1 0 1
28 28- 11101 29 1 1 1 0 1
29 29-11001 25 1 1 0 0 1
30 30- 01001 9 0 1 0 0 1