Twitter YouTube SoundCloud LinkedIn

Tiennot blog

Un (web)gradateur de lumière

Sur cette page, vous retrouverez toutes les explications détaillées sur la réalisation du gradateur de lumière présenté dans cette vidéo. Les liens pour télécharger les codes sources se trouvent en bas de page. Bonne lecture !

Mises en garde

Avant de commencer à détailler le montage, quelques avertissements s'imposent. Déjà, la plus grande prudence est de rigueur pour la partie puissance du circuit. Celle-ci travaille directement sur le secteur sous 230 volts. Ainsi, il convient de bien l'isoler : aucune manipulation dessus tandis qu'elle est alimentée ! De plus, faites très attention à éviter tout contact entre la partie puissance et commande, qui, elle, fonctionne sous 5 volts. Deux fils vacants ont trop vite fait de se rencontrer... Le montage doit donc être impeccable. Enfin, l'optocoupleur et l'optotriac (voir schéma) sont indispensables pour isoler parfaitement les deux parties du circuit. N'établissez jamais de point commun entre le secteur et la masse du circuit de commande !

Ces précautions, somme toute classiques, ne sont pas les seules à prendre : faites bien attention à la charge reliée au montage. N'utilisez surtout pas de lampe à économie d'énergie, car vous aurez vite fait de la détruire, ainsi que votre précieux circuit. La lampe à utiliser doit être à filament (incandescente classique ou halogène). D'une manière générale, ne reliez aucune charge comportant un onduleur ou une alimentation à découpage : le résultat risque d'être catastrophique. De plus, si vous souhaitez remplacer la lampe par un autre dispositif (moteur par exemple), il vous faudra peut-être adapter le montage. En effet, celui-ci a été conçu pour une charge purement résistive, telle qu'une lampe. Dans le cas d'un moteur, donc charge inductive, le courant et la tension sont déphasés d'une certaine valeur. Dès lors, il vous faudra adapter les valeurs de la résistance et du condensateur qui protègent le triac si vous tenez à sa durée de vie...

Vous êtes donc pleinement responsable des dégâts que pourrait causer l'utilisation d'un tel montage. Celui-ci présentant certains risques, il est indispensable de faire preuve de la plus grande prudence. Vous voilà avertis ; nous pouvons donc passer aux explications techniques.

Vue d'ensemble du montage

Le montage se découpe en trois blocs principaux, que nous allons détailler dans cet ordre : un étage de puissance pour commander la lampe, une carte électronique de commande, qui a pour rôle de contrôler l'étage de puissance et d'assurer la communication avec l'utilisateur, et enfin une webapplication, qui assure l'interface avec l'utlisateur.

Schéma global
Schéma global du gradateur

Pour bien comprendre comment fonctionne le prototype, il est nécessaire d'expliquer chaque bloc séparément. Mais avant cela, commençons par étudier le principe physique sur lequel s'appuie le bloc de commande.

Un peu de physique...

Le principe fondamental du montage est le même que celui utilisé pour le hacheur série. Cependant, une différence flagrante apparaît entre les deux réalisations : l'une fonctionne en courant continu, l'autre en alternatif. Ainsi, lorsque pour le hacheur série on « découpait » le courant reçu par la charge à l'aide d'une haute fréquence, il ne sera pas possible de faire la même chose pour notre gradateur, car la tension utilisée à la base est déjà alternative.

La solution est donc d'exploiter le signal tel qu'il nous est fourni. Rappelez-vous : toute la subtilité du hacheur série réside dans la variation du rapport cyclique de la fréquence de hachage. Et bien nous allons faire la même chose avec le secteur. Le gradateur de lumière fonctionne donc ainsi : il suffit, à chaque demi-période du signal alternatif, de faire varier l'énergie reçue par la charge. Pour ce faire, il faut déclencher le passage du courant plus ou moins tôt dans la demi-période. La charge étant assimilable à un filtre passe-bas, tout va se passer comme si elle recevait un signal de puissance variable.

Principe du gradateur
Principe physique (cliquez pour agrandir).

Voici donc la raison d'être de l'avertissement en début de page : la charge doit se comporter comme un filtre passe-bas, ce qui n'est pas le cas des lampes à économie d'énergie ou des alimentations à découpage. En effet, observez attentivement le schéma : vous comprendrez rapidement qu'elle reçoit en fait des « morceaux » de sinusoïde, et non un beau signal bien propre. Ainsi, des hautes fréquences se glissent dans le spectre du signal reçu, ce qui peut perturber les appareils branchés dessus. D'ailleurs, c'est également la raison d'être du filtre réjecteur présent en début de montage, que vous allez découvrir dans quelques lignes : il évite de perturber les autres appareils sur secteur avec les hautes fréquences générées par le circuit.

L'étage de puissance

Voyons maintenant le fonctionnement de l'étage de puissance, dont le schéma se trouve juste en-dessous.Ce dernier s'articule autours d'un composant fondamental dans ce genre d'applications : le triac.

Schéma électronique
Schéma électronique (cliquez pour agrandir)

Le triac est un composant à trois broches très similaire au transistor. Il possède deux bornes constituant le signal contrôlé (les anodes), et une borne de commande (la gâchette). Cependant, l'analogie s'arrête là. Le triac possède en effet une propriété intéressante par rapport au transistor : lorsqu'une impulsion est envoyée sur la gâchette, le composant reste passant tant qu'un certain courant circule entre ses anodes. On retrouve ce même fonctionnement chez un autre composant électronique, le thyristor. Cependant, le triac possède une propriété supplémentaire : il est passant dans les deux sens. Ainsi, son utilisation est toute indiquée en courant alternatif.

triac
Triac

À présent, remontez voir le schéma explicatif de la partie précédente. Vous comprenez alors le principe : on envoie une impulsion par demi-période au triac. Suivant l'instant auquel est envoyée l'impulsion, la charge va recevoir plus ou moins d'énergie. Il reste un détail à régler : il faut connaître l'instant où l'onde du secteur passe par zéro, pour se synchroniser dessus, et envoyer l'impulsion au bon moment. C'est la raison d'être de l'optocoupleur...

Juste avant d'expliquer le fonctionnement de la détection par zéro, expliquons en quelques mots l'isolation galvanique de la partie commande du montage. Comme il a été dit dans les avertissements en début de page, il est vital (au sens propre) de maintenir une séparation absolue entre le secteur et celle-ci. Pour ce faire, les impulsions de commande générées par l'Arduino sont envoyées au triac à travers un optotriac. Ce composant possède un fonctionnement similaire à celui de l'optocoupleur - à savoir qu'il isole optiquement les circuits - à ceci près qu'il fonctionne dans les deux sens. Ainsi, on peut utiliser le courant alternatif du secteur en commande, moyennant bien sûr une résistance, pour diminuer la tension de celui-ci.

Dans la même optique (admirez le jeu de mots !), l'optocoupleur sert à isoler la détection du zéro secteur. En exploitant sa LED de commande, on peut le rendre passant à chaque fois que le courant qui circule passe en-dessous d'une certaine valeur - en réalité bloquant, mais le signal est inversé en sortie à l'aide d'une résistance de pull-up. À partir de là, il n'y a plus qu'à ajouter en sortie un trigger de Schmitt (CMOS CD 4093 par exemple) pour obtenir un signal bien carré. Reste un petit détail : la LED de l'optocoupleur risque d'être détruite. En effet, si elle est branchée telle quelle sur le secteur, même encadrée de deux résistances de 150 kOhms pour en diminuer la tension, elle va subir une tension inverse de 230 volts, suivant la polarité de l'onde, et donc être détruite. Il ne faut donc pas oublier d'ajouter une diode en inverse pour permettre l'établissement du courant dans ce sens (merci Leroilion pour cette précision). J'ai choisi pour mon montage un dispositif légèrement différent : j'ai relié l'optocoupleur à la sortie d'un pont de diodes. Ainsi, les impulsions reçues sont toutes positives.

La webapp

Du côté de la webapplication, pas grand chose d'original. Celle-ci consiste en une page HTML, alliée à une feuille de style CSS et un programme en javascript. En utilisant ces technologies, on a l'assurance que l'application est compatible avec presque tous les supports existants.

L'envoi d'informations se fait de manière asynchrone, au moyen de requêtes ajax. Celles-ci contiennent simplement la valeur du potentiomètre, un entier compris entre 0 et 255. Il y a ainsi 256 valeurs d'éclairage possible, ce qui est amplement suffisant pour une application de ce genre. Une requête est envoyée à chaque mouvement du gradateur ; la luminosité est donc censée être la plus linéaire possible - ce qui n'est pas toujours le cas en pratique, comme nous le verrons plus loin.

aperçu de l'application aperçu de l'application
Quelques captures de l'application

Voyons enfin les quelques adaptations nécessaires pour rendre cette application compatible avec les supports mobiles. L'utilisation des directives viewport pour éviter le zoom et adapter le contenu à la largeur de l'écran est indispensable (une petite recherche sur internet avec ce mot-clé vous en apprendra plus). Il ne faut pas oublier également que les évènements javascript à intercepter ne sont pas les mêmes : il faut en effet réagir aux ontouchstart, ontouchmove et ontouchstop en lieu et place de onmousemove... Enfin, toujours dans les balises meta, la définition d'une icône d'application vous permettra d'ajouter un joli signet sur le « bureau » de votre téléphone, comme s'il s'agissait d'une véritable application mobile !

N'hésitez pas à consulter le code source, disponible en bas de page, pour en apprendre plus. À présent, voyons le cerveau du montage : l'arduino.

Le cerveau : l'Arduino

La webapplication étudiée dans la section précédente est hébergée directement sur la carte Arduino. Les fichiers HTML, CSS et javascript de celle-ci sont envoyés au smartphone grâce à un petit serveur. Il s'agit ni plus ni moins d'un serveur HTTP qui répond aux requêtes qui lui sont envoyées. Pour éviter de perdre du temps en développement, et afin de simplifier le code, il a été choisi d'utiliser la bibliothèque Webduino. Celle-ci propose de générer simplement un petit serveur HTTP qui répond aux requêtes dans la boucle principale de l'Arduino. Profitons-en pour rappeler, au passage, qu'il est indispensable de posséder un shield ethernet compatible pour espérer voir le serveur fonctionner...

À ce stade, quelques précisions s'imposent sur l'hébergement des fichiers. Étudions pour commencer les spécifications de l'Arduino Uno, carte utilisée dans ce montage. Sur le site officiel (http://arduino.cc/en/Main/ArduinoBoardUno), nous pouvons voir que celui-ci dispose de 32 kio de mémoire flash programmable, 2 kio de SRAM et 1 kio de mémoire EEPROM. Nous ne parlerons pas de cette dernière, car elle ne nous sera pas utile dans cette application ; sachez simplement qu'elle est utile pour sauvegarder des données de manière permanente, même en cas d'extinction de l'alimentation. La mémoire flash sert à enregistrer votre programme compilé sur la carte. La mémoire SRAM, quant à elle, est utilisée par le microcontrôleur pour stocker le contenu des variables définies par l'utilisateur dans son programme. Et c'est là qu'arrivent les ennuis... En effet, 2 kio de mémoire vive, c'est bien peu pour toutes les variables du programme : la taille totale des fichiers à héberger est plus élevée. Si vous tentez malgré tout de stocker les pages web dans des variables classiques, vous obtiendrez un comportement aléatoire du programme, dû à un dépassement de la taille maximale de la mémoire. La seule solution - enfin, pas exactement, comme vous le verrez par la suite - est d'enregistrer nos fichiers là où il y a de la place, c'est-à-dire dans la mémoire flash de l'Arduino. Pour voir comment procéder, reportez-vous au fichier files.h du projet.

Le problème de l'hébergement étant résolu, venons-en au cœur du programme. Commençons par aborder la question de la détection des passages à zéro de l'onde secteur. Une solution, peu élégante, consisterait à tester à chaque tour de boucle la valeur d'une pin reliée à l'optocoupleur. Bien entendu, ce ne sera pas le principe retenu ici. Nous allons utiliser les interruptions disponibles sur la carte. Pour rappel, une interruption est une fonction qui est déclenchée par le microcontrôleur lorsque survient un évènement interne (compteur) ou externe (changement d'état logique), interrompant alors le cours normal du programme.

L'arduino Uno possède deux sources d'interruptions externes programmables, sur les pins numériques 2 et 3. L'interruption 0, correspondant à la broche 2, n'est pas disponible, car déjà utilisée par le shield ethernet. Nous utiliserons donc l'interruption 1, qui réagit aux signaux envoyés sur la broche numérique 3 de la carte. À chaque front descendant du signal, nous déclencherons la procédure associée, qui consistera simplement à, d'une part, mettre une variable booléenne à l'état vrai, signe qu'un zéro est passé, et d'autre part à récupérer la valeur en microsecondes du compteur de temps interne à l'Atmega 328. Ensuite, par simple différence de temps par rapport à cette valeur, on peut savoir la durée écoulée depuis le dernier passage à zéro de l'onde secteur.

La suite du calcul consiste à déterminer le temps au bout duquel il convient d'envoyer une impulsion au triac pour allumer la lampe. Étant donné que la fréquence du secteur est fixe, il est possible de stocker statiquement dans une macroconstante la valeur de la demi-période du signal (en l'occurence, 10 ms). Ensuite, il faut se rappeler que l'application envoie la luminosité à appliquer sous forme d'un entier d'une valeur comprise entre 0 (éteint) et 255 (luminosité maximale). Enfin, appliquez la formule suivante : t = ((255 - x) / 255) * T avec t la durée recherchée, T la demi-période, et x la valeur du gradateur.

Il nous reste un dernier point à aborder avant de terminer cette section : l'envoi de l'impulsion au triac. La solution la plus simple consiste à tester à chaque itération de la boucle principale si le temps écoulé depuis le dernier passage à zéro est supérieur ou égal à la durée calculée précédemment. Cependant, cet algorithme fonctionne plutôt mal en pratique. Il s'avère que le serveur web prend un temps d'exécution non négligeable, rendant instable la luminosité de la lampe, les impulsions étant alors envoyées souvent en retard. Il a été choisi d'utiliser une source d'interruption interne au microcontrôleur, liée à son compteur de temps. Concrètement, nous exécuterons une procédure réalisant le test spécifié plus haut, et émettant une impulsion le cas échéant, à intervalle régulier. L'utilisation d'une interruption nous garantit que le test est effectué régulièrement, et non suivant les caprices de l'application web.

Pour implémenter cette solution, il a été choisi d'utiliser la bibliothèque TimerOne, qui offre l'avantage de faciliter la mise en œuvre des interruptions internes. La durée de déclenchement a été fixée à 30 microsecondes. Cette durée est un compromis entre la réactivité du serveur web, et la précision de la luminosité de la lampe. Si cette valeur est diminuée, la webapplication est beaucoup plus lente à réagir. Inversement, si le délai dépasse 40 microsecondes, on ne profite plus pleinement des 256 valeurs possibles de luminosité - le pas vaut environ 39 microsecondes.

Les limites du montage

Pour finir, parlons un peu des solutions disponibles pour améliorer le montage. Du côté du bloc de puissance, pas grand chose à signaler : c'est un montage classique, maintes fois revu sur internet. La plupart des améliorations possibles concerne donc l'Arduino.

Rappelez-vous, nous avons parlé précédemment du problème soulevé par l'hébergement des fichiers de la webapplication. Ceux-ci sont en effet trop volumineux pour être stockés sous forme de simples variables en mémoire SRAM ; il a fallu les enregistrer dans la mémoire programme du microcontrôleur. Fait intéressant, le shield ethernet possède un lecteur de carte micro-SD. Il est ainsi possible, via les bibliothèques Arduino, de stocker des données dessus. L'intérêt est évident : on libère une place non négligeable en mémoire flash.

Autre problème, également soulevé précédemment : la puissance de calcul de l'Arduino. Expérimentalement, on constate que la précision de la luminosité se fait au dépend du temps de réponse du serveur web, et vice versa. Dans la configuration retenue, il a été décidé de laisser la priorité à l'envoi des impulsions, au moyen d'une interruption interne pour être sûr qu'elles soient envoyées à intervalles réguliers. Le serveur web prend donc la puissance de calcul restante, ce qui, finalement, ne représente pas beaucoup de temps d'exécution. L'utilisation d'une carte plus puissante, telle la Pandaboard, autoriserait une plus grande souplesse dans la gestion des ressources. Il faudra, bien entendu, veiller à accorder des priorités temps réel à la détection du zéro secteur et à l'envoi d'impulsions, sous peine de se retrouver avec des luminosités très instables.

Avec une carte plus puissante, il devient également possible d'augmenter la résolution des luminosités appliquées. Actuellement, celle-ci est de 256 valeurs, ce qui est déjà amplement suffisant pour l'œil humain. L'intérêt n'est donc pas flagrant. Par contre, il pourrait être intéressant d'améliorer les transitions de luminosité. Vous l'avez peut-être remarqué dans la vidéo : le changement est plutôt abrupt. Lorsqu'on analyse les requêtes envoyées par le smartphone, on se rend compte qu'un bon nombre d'entre elles ne parviennent pas au serveur, le navigateur décidant de simplement les annuler, car elles sont trop rapprochées dans le temps. N'oublions pas en effet que chaque requête envoyée nécessite l'établissement d'une nouvelle connexion avec le serveur...

Pour résoudre ce problème, il faudrait obtenir une connexion persistante avec le serveur. L'utilisation d'une carte de développement plus puissante nous offre alors l'opportunité de travailler avec une technologie intéressante : le NodeJS. Il n'est pas dans des objectifs de cette page de proposer au lecteur un cours détaillé sur cette technologie ; pour en apprendre plus, celui-ci pourra se reporter à l'un des nombreux tutoriels disponible sur internet. Avec NodeJS, il devient possible de conserver une connexion permanente entre le smartphone et le serveur. Les bénéfices potentiels sont énormes. Les transitions de luminosité devraient être moins abruptes, grâce à l'envoi de plus de valeurs intermédiaires. En outre, le système deviendrait presque insensible aux latences réseau. Ce fait vous a peut-être frappé dans la vidéo : la réponse de l'Arduino aux requêtes qui lui sont envoyées n'est pas toujours immédiate, dû au temps nécessaire à l'établissement d'une nouvelle connexion, et surtout à la charge du réseau, plutôt aléatoire, qui peut augmenter fortement ce délai. L'établissement d'une connexion persistante nous permet de nous acquitter une seule fois de cette procédure, offrant en théorie une réactivité plus élevée.

Enfin, dernier bénéfice attendu de NodeJS, et non des moindres : le support de plusieurs clients simultanés. Grâce aux connexions persistantes, il devient possible de répercuter sur le téléphone de chaque utilisateur les changements effectués par les autres. Cependant, il ne faudra pas oublier de gérer les accès concurrentiels au système, au moyen par exemple de sémaphores, sous peine de se retrouver avec un comportement aléatoire de l'application.

Téléchargements

Fichiers web (GNU/GPL 3)
Librairie pour le serveur web (CC-BY-SA)
Librairie TimerOne pour Arduino (GNU/GPL 3)
Projet Arduino (web)gradateur (GNU/GPL 3)