lundi 16 décembre 2013

chandelle électronique

Ce matin je suis tombé sur cet article. L'auteur de ce blog a analysé le signal d'une chandelle électronique afin de reproduire l'algorithme. Une chandelle électronique est en fait une LED dont l'intensité varie de façon aléatoire de manière à imiter le scintillement d'une vrai chandelle. Je n'ai jamais utiliser une telle LED j'étais donc curieux de voir de quoi il en retourne. J'ai donc examiner le code de l'auteur du blog cpldcpu. Le code est écris en 'C' pour un ATtiny mais je me suis dis que c'était un projet idéal à exécuter sur le plus simple et économique des MCU disponible sur le marché, soit le PIC10F200. En m'inspirant du code source original j'ai écris ma propre version en MPASM pour le PIC10F200. Rien de plus simple comme montage, un PIC10F200 avec une LED jaune directement branchée sur la broche GP2.

J'ai utilisé le même PRNG basé sur un LFSR de 32 bits. Cependant j'ai fait 2 modifications. D'abord dans le code original il y a un bogue2, la variable randflag n'est jamais remise à zéro à l'intérieur de la boucle while. Donc une fois qu'elle a été mise à 1 elle y reste et devient inutile.

L'algorithme original autorise des fluctuations d'intensité pouvant descendre jusqu'à 25% (si le bogue est corrigé1 sinon ça peut descendre jusqu'à zéro). J'ai essayé ça mais je n'étais pas satisfait du résultat. Je trouvais les écarts d'intensité trop grand par rapport à une vrai chandelle. J'ai donc modifier le programme de la manière suivante. D'abord je me suis débarrassé de randflag qui est inutile dans ma version. Deuxièmement j'ai fait en sorte que le rapport cyclique du PWM varie de 50% à 100% au lieu de 25% à 100%. Je trouve ainsi que l'effet est plus ressemblant à une chandelle.

Code source en MPASM

On a donc une modulateur d'intensité pwm_control avec une résolution de 4 bits . L'intensité est contrôlée par variation du rapport cyclique d'une onde rectangulaire dont la fréquence est d'environ 440hz. On a un générateur de nombres pseudo aléatoire lfsr_rand. Pour cette application on ne garde que les 5 bits les moins significatifs qu'on conserve dans rand_val. Le délais pour contrôler la fréquence du modulateur PWM est assuré par la minuterie TIMER0. l'intensité de la LED est modifiée à tous les 32 cycles PWM par la variable frame_cntr qui est incrémentée modulo 32. Pour la valeur du rapport cyclique pwm_val on procède comme suis. Si la valeur de rand_val est inférieur à 16 on utilise la valeur maximale soit 15 (LED à intensité maximale). Si La valeur est >=16 on divise rand_val par 2 et on utilise cette valeur comme rapport cyclique. Donc statistiquement l'intensité de la LED devrait-être à son maximum 50% du temps et pour les 50% restant n'importe quelle valeur entre 50% et 100%.


1) pour corriger le bogue du code 'C' disponible sur github remplacez la ligne:

if ((RAND&0x0c)!=0) randflag=1; // only update if valid 
par
if ((RAND&0x0c)!=0) randflag=1;else randflag=0; 

2) 2013-12-17: J'ai passé le message à l'auteur concernant le bogue et il a fait la correction.

4 commentaires:

  1. je l'ai mis dans la cheminée de mon Père Noël, ça donne pas mal, je pense qu'avec un transistor sur GP2 on peut faire une feu de joie à plusieurs LED Merci :=)

    RépondreSupprimer
  2. Etait-ce vraiment un bogue? Une (vraie) chandelle ne s'éteint jamais quand elle scintille....

    RépondreSupprimer
    Réponses
    1. Je ne saisis pas trop la question. En effet la flamme d'une chandelle fluctue en intensité mais cette intensité ne descend jamais à zéro. Lorsque je fais référence à un bogue dans le code original de cplcpu je mentionne le fait qu'il défini et initialise la variable randflag mais celle-ci n'est jamais modifiée à l'intérieur de la boucle while...

      Pour ce qui est du code que j'ai écris l'intensitée perçue de la LED ne descend à jamais à zéro mais varie entre 50% et 100%. Il s'agit d'une modulation PWM alors il est évident que la LED est éteinte mais c'est trop rapide pour être perçu par l'oeil.

      Supprimer
    2. Vérification faite cpldcpu a corrigé le bug dans son code le Dec 17, 2013.
      ref: https://github.com/cpldcpu/CandleLEDhack/blob/master/Emulator/CandeflickerLED.c

      Supprimer