Utilisation d'un microcontrôleur sur le secteur

Le circuit cible est un microcontrôleur faible coût, PIC12C508 ou PIC16F628 avec horloge interne Fx=4 MHz -8/+10%.

 

Circuit

Tension

Consommation

Horloge interne

PIC12C508A

3-5,5V

1,4mA max @5,5V ; 0,8mA typ @5,5V

4 MHz -8/+10%

PIC16F628A

3-5,5V

1,3mA max @5,5V ; 0,8mA typ @5,5V

4 MHz -9/+7%

 

L'horloge interne n'est pas précise, et sensible à la température. Ce qui veut dire que sa valeur peut évoluer dans le temps ; par exemple +2% au démarrage à froid et +3.7% après quelques minutes de chauffe. Il faudra la mesurer (avec le secteur lui même) puis appliquer des corrections. On va développer une solution avec un oscillateur numérique asservi. Evidemment une solution à Quartz est plus simple, mais elle est plus chère.

L'alimentation sera prélevée directement sur le secteur, au travers d'une capacité. Par exemple 50nF+2k donne 1,6mA moyens, avec un condensateur de filtrage 100µF, ripple de 100mV. Montée à 5V en 0,5s.

Fondamentalement, c'est un circuit de découpage de phase. Le µlogiciel employé peut être rustique : attendre x ms après le passage à zéro puis amorcer le triac. Le nombre de pas nécessaires pour régler la puissance en sortie peut être raisonnable (le circuit LS7631 en a 83, les dimmer DMX512 en ont 256 dont les LSB ne sont pas forcément employés). En utilisant une résolution de 1µs, on a le choix entre les solutions suivantes :

Si on souhaite garder le nombre de pas inférieur à 255 pour tenir sur un octet, alors on considèrera un quantum à 64µs, ce qui offre 156 pas par demi-période.


Premier cas : gradateur simple

Le cas simple consiste à utiliser un PIC12C508, et son timer TIMER0, avec un quartz 4MHz et une détection secteur des 2 fronts, montant et descendant. Chaque demi période est divisée en plusieurs tranches temporelles, ou modes, ce qui permet une écriture aisée du logiciel

Principe

Au passage à zéro du secteur, on charge le timer avec une valeur "N0", sauf qu'en fait on ne connaît pas bien l'instant du 0 secteur.

En supposant une détection directe sur une entrée du microcontrôleur avec une résistance élevée (2 x 330k par exemple) et une capacité de filtrage de 39pF pour être moins sensible à la HF et 7pF de capacité parasite, la montée du signal logique « détection de zéro » se fera 140µs après le vrai zéro secteur. Dans ces conditions, il ne faudrait pas charger N0 mais N0+140µ/résolution soit à peu près N0+2.

Arrivée à 255, le timer passe à zéro et active une interruption qui va changer le mode, c'est à dire autoriser un amorçage du triac.

La valeur de N0 va de 255 (plein feu), à maxdim (minimum).

La valeur de maxdim est telle que le compteur déborde à la fin de la demi période, Ta=10ms, Tb=0, N1=0, donc maxdim = 256-0.01*Fx/256 dont maxdim=99.75 [84.1 : 115.4] à 50 Hz.

Pour n'importe quelle N0 on a l'équation N = N0 - maxdim, à chaque passage à zéro, en lisant N1, on en déduit une valeur de maxdim = N0 - N1.

Divers considérations :

Algorithme :

 

Attendre le zéro secteur ; en fait on attendra le front

Si N0>timer0, Maxdim = N0 - timer0 ; timer0 = 0.01*Fx/256 - 256 + N0

Sinon maxdim=maxdim+256-timer0

N0 = min (N0, maxdim) ; clamp

Charger le timer avec N0 ; le compteur s'incrémente toute les 256/Fx

Attendre Timer=0 ; attention cet état ne dure que 64µs

Amorcer le triac ; impulsion de quelques µs

Attendre le zéro secteur

etc

Analyse temporelle pour définir la machine à états

Dans tous les cas, lorsqu'on recherche des fronts montants ou descendants, on fera systématiquement plusieurs acquisitions successives pour éviter le déclenchement sur parasite.

La détection des fronts sera armée x µs avant de façon à être robuste à des parasites. Si le front n'est pas détecté dans une fenêtre prédéfinie,

On découpe la période en plusieurs tranches.

Détection simple

En utilisant un seul signal de détection de zero, D1 à +2.5V, on considère 4 tranches.


Mode

Localisation entre ...

et …

Tache

0

...

D1+

Si front montant D1 alors
  N1 = timer0
  Timer0 = N0+offset1
  mode = 2

1

D1+

OVF timer0

Attente OVF et passage au mode 2

2

OVF timer0

D1-

Activation Triac, 50µs tous les 500µs
Si front descendant D1 alors
  N2 = timer0
  Timer0 = N0-offset2
  mode = 4

3

D1-

OVF timer0

Attente OVF et passage au mode 4 (->0)

 

N2+100h-(N0+off1) = D1un

 

N1+100h-(N0-off2) = D1zero

 

D1zero - D1un = 2off1 + 2off2
Ou encore : Off1 + Off2 = N1 - N2

Impossible de discerner off1 de off2

Détection double

En utilisant deux détections de zéro, D1 et D2, on considère 8 tranches.



Pour un gradateur simple

 

N3+100h-N2 = D1un
N1+100h-N4 = D2zero
N2-(N0-off1) = 2.off1 si D1/D2 appairés
N4-(N0-off2) = 2.off2 si D1/D2 appairés
N2-(N0-off1) + N4-(N0-off2) + D1un = D2un
N2-(N0-off1) + N4-(N0-off2) + D2zero = D1zero


 

Si _e=01h

Si D2=111 alors _e=02h

Si _e=02h

_N1=timer0
timer0=_N0-_offset1
_fire=0
_e=04h

Si _e=04h

Si D1=111 alors _e=08h

Si _e=08h

_N2=timer0
_e=10h

Si _e=10h

Si D1=000 alors _e=20h

Si _e=20h

_N3=timer0
timer0=_N0-_offset2
_fire=0
_e=40h

Si _e=40h

Si D2=000 alors _e=80h

Si _e=80h

_N4=timer0
_e=01h

Sinon

Erreur ?

Si _fire=1

Décrémente _tfire
Si _tfire=0 alors
  Pulse IOgate ; tfire=10

Interruption _timer=0

_fire=1

   

Pour un hacheur qui laisse passer quelques demi périodes entières seulement

Si _etat=7(80h)

Si TMR0>=DP-1 alors _etat=0

Attente fenêtre synchro

Si _etat=0(01h)

Si D2=111 et D1=000 alors
  TMR0=0
  Incrémente _arche
  Si _arche=1 alors _fire=1
  _etat=1

Passage 0 arche positive
Amorçage triac si _arche=1

Si TMR2>=DP+1 alors
  TMR0=0
  Incrémente _arche
  Si _arche=1 alors _fire=1
  _etat=1
  erreur++
  si erreur>=errmax alors goto reset

Absence de synchro, on fait pareil et on incrémente le compteur d'erreur

Si _etat=1(02h)

Si TMR0>=2 alors fire=0
Si D1 = 111 alors
  _etat=2

Fin d'amorçage triac à 128µs
Attente front montant de D1

Si _etat=2(04h)

 

Etat libre

Si _etat=3(08h)

Si TMR0>=DP-1 alors _etat=4

Attente fenêtre synchro

Si _etat=4(10h)

Si D1=000 et D2=111 alors
  TMR0=0
  Incrémente _arche
  Si _arche=2mode+2 alors _fire=1
  Si _arche=4mode+2 alors _arche=0
  _etat=5

Passage 0 arche négative
Amorçage triac si _arche=x

Si TMR2>=DP+1 alors
  TMR0=0
  Incrémente _arche
  Si _arche=2mode+2 alors _fire=1
  Si _arche=4mode+2 alors _arche =0
  _etat=5
  erreur++
  si erreur>=errmax alors goto reset

Absence de synchro, on fait pareil et on incrémente le compteur d'erreur

Si _etat=5(20h)

Si TMR0>=2 alors fire=0
Si D2 = 000 alors
  _etat=6

Fin d'amorçage triac à 128µs
Attente front descendant de D2

Si _etat=6(40h)

 

Etat libre

 

La durée totale de la boucle est de 6 tests (BTFSS GOTO) soit 6*(1+2)=18µs @4MHz, bien inférieure à la résolution TMR0.


Deuxième cas : circuit évolué à PLL

Le cas évolué consiste à utiliser un PIC16F628, et son timer TIMER1, sur oscillateur interne et une détection secteur simple. L'amorçage triac se fait de façon intelligente et des courbes de correction de puissance sont implantées.

Le circuit utilisé doit être robuste aux parasites. Il faut qu'il ait une horloge propre, en phase avec le secteur. On ne peut pas compter sur la détection au zéro pour cadencer tout le processus.

On peut utiliser l'horloge interne et se passer de quartz, si on met au point un asservissement, comme une PLL. Par exemple, à chaque passage à zéro secteur, on échantillonnera le timer pour générer une erreur, qui sera utilisée pour corriger la consigne en fréquence.

Dans ce cas on utilisera une détection secteur simple, à 20ms, il suffit qu'elle soit précise, c'est à dire que la gigue soit aussi faible que possible, pour toujours échantillonner précisément au même instant.

L'oscillateur piloté

Dans toute PLL il y a un oscillateur piloté, il sera réalisé par un timer rechargé périodiquement.

On supposera que la fréquence de l'horloge est 4MHz.

Le choix du timer est très limité dans la série PIC :





Cette dernière solution est la plus stable et la plus simple à mettre en oeuvre. La fréquence de sortie de cet oscillateur est égale à Fxtal/N0, et doit être égale à 100Hz.

Ce choix disqualifie les microcontrolleurs de la série PIC12.

Etalonnage

Dans le cas d'un montage sans quartz, sur horloge interne, il est nécessaire de faire une calibration au démarrage, en mesurant n périodes secteur, pour trouver la valeur précise de N0 et démarrer ainsi la PLL à la bonne fréquence.

Avec un timer de 16 bits, tournant à 1MHz, on pourrait aller jusqu'à mesurer 3 périodes entières, mais 2 suffiront et on évitera ainsi des divisions compliquées.

L'horloge interne à 4 MHz étant donnée à +/-5%, la valeur mesurée sur 2 période est égale à 2*Fq/50, valeur nominale = 40000 (0x9C40) +/-5%.

La valeur à recharger est pour une demi période est donc N0 = N/4 = 10000 (0x2710) +/- 40 (0x0028), elle doit être comprise entre 9500 (0x251C) et 10500 (0x2904).

Une valeur plus forte trahit une horloge locale trop rapide.

Boucle de phase

A chaque front montant de la détection zéro secteur, toutes les 20ms, une interruption EXT0 est générée et le timer1 est échantillonné. Comme nous utilisons le registre CCPR1 pour le rechargement, cet échantillonnage sera réalisée par double lecture TMR1H/TMR1L selon les recommandations de Microchip.

Un écart fréquentiel de 0.1% se traduit par une fréquence de battement de 0.05Hz soit une période de 20s, et un écart entre 2 échantillons successifs de l'ordre de 10.

 

Si le front de montée de la détection zéro est présent entre 50 et 10µs avant le vrai zéro (soit détection entre -5V et -1V), on s'attend à ce que la valeur du timer soit comprise entre N0-50 et N0.

Si on veut asservir la phase autour de ce 0, il faut décaler les valeurs lues pour qu'elles soient continues à cet endroit, sinon les calculs risquent d'être très compliqués. Ainsi l'asservissement travaillera autour de N0/2.

Il faut maintenant appliquer le filtre de boucle afin de calculer en temps réel la nouvelle valeur de l'oscillateur.

Rappel sur le filtrage numérique

Source :

Un filtre numérique récursif ou non récursif réalise la fonction numérique suivante :

Il a pour fonction de transfert

Le gain en continu est obtenu en faisant z=1 et le gain à l'infini (à la fréquence de Shannon = Fech/2) en faisant z=-1

Transformation bi linéaire

On passe de la transformée en Z à la transformée de Laplace avec les relations et .

En développant en série et en se limitant au premier ordre :

et et

Le point p= 0 se transforme en z = 1, tandis que p= se transforme en z = -1

Exemple de synthèse :

1er ordre, 1 pole, 1 zéro

 

Voir aussi table d'équivalence plus complète chez université de Bordeaux

NOTA : utilisation de J-DSP editor, problème de signes de A0, A1, A2

On retrouve le premier avec A0=1, A1=-0.909, A2=0.818, B0=0, B1=0.909

Transfert du NCO

L'oscillateur numérique (NCO) piloté par le timer 1, se comporte comme un intégrateur par rapport à Fxtal. A chaque échantillonnage de sa phase, toutes les 20ms (à 50Hz), une valeur phi est lue.

, N0 étant la consigne, c'est à dire la commande appliquée au NCO.



En considérant que l'entrée, on peut écrire cette équation , elle a pour transfert :

, gain infini à f=0 (z=1), et -6dB à f=Fe/2=25Hz (z=-1)

 

C'est un magnifique intégrateur 1/p (un pole à z=1, et un zéro à z=0), la boucle de phase devra comporter au moins un zéro afin d'avoir un système stable.

En considérant un filtre simple avec un transfert du type , le système NCO+filtre peut se symboliser comme suit :



On peut écrire . Si on considère que Fxtal/200 est l'entrée, on en déduit la fonction de transfert , qui donne H(0)=0 et H(infini)=1/(2-b0+b1)

 

Ceci est un filtre IIR, avec B0=1, B1=-1, A0=1, A1=2b0-2 et A2=1+2b1

Avec 2 zéros : [0;0], [1;0] et 2 pôles conjugués [1- b0;+/-rac((b0-1)²-1-2b1)]

Pour simuler de tels filtres, j'ai acquis la phase en boucle ouverte, mesurée sur la maquette (courbe bleue). Cette série montre un décalage moyen de l'ordre de 2,8 par période de 20ms (700 sur un horizon de 5 secondes), soit un écart en fréquence de 0.028% après calibration. Avec une telle entrée il est facile de simuler sur le comportement du filtre de boucle sur le NCO au global.


Prenons une exemple, avec b0=0.50 et b1=-0.45.

On constate que ce filtre offre un amortissement fort, la consigne est atteinte en 1 seconde, avec un résidu crête-crête de 12.

Le transfert équivalent a été simulé : A0=1, A1=2b0-2=-1, A2=1+2b1=0.1, B0=1, B1=-1


On a implanté sur la maquette les coefficients b0=0.5 et b1=-0.25 très faciles à coder (shift droit), avec un calcul sur 8 bits, donc avec sans doute pas mal d'erreur. Le transfert équivalent a été simulé : A0=1, A1=2b0-2=-1, A2=1+2b1=0.5, B0=1, B1=-1

L'amortissement n'est pas optimal, le système est un peu trop rapide, le bruit en sortie est plus fort, mais çà fonctionne quand même.


 

La figure ci dessous donne l'allure de N0, sur presque 2000 périodes (40 secondes), avec b0=0.5 et b1=-0.25 avec un calcul sur 8 bits. Les erreurs dues à l'arrondi sont grandes, le bruit crête à crête est de 6 à 10 unités.

 

 

Le démarrage du NCO montre que l'amortissement du filtre n'est pas optimal, par contre il est très rapide, on converge à +/-10 en moins de 6 périodes de 20ms. On voit aussi que le filtre fonctionne si Phi est supérieur à 5, c'est le seuil qui a été choisi sur la maquette.

L'implantation sur micro nécessite un peu de soin pour éviter les erreurs d'arrondi. Si la phase est sur 16 bits signés, on fera les calculs sur 24 bits signés en utilisant des coefficients b0, b1 sur 8bits signés.

Un arrondi propre est pratiqué pour éviter que la convergence de la boucle soit égale à 0.5/(b0+b1).

Une série d'essais a été réalisées avec différentes valeurs de b0,b1, avec un seuil de mise en route à +/-5 (l'algorithme tourne si |phi|>5).

Les courbes pleines sont représentent N0, les pointillés la phase Phi.

Echantillonnage de la phase interne sur zéro secteur.

On utilise une détection simple, en envoyant le secteur au travers de 2 résistances de 330k, sur la broche RB0/INT. Une routine d'interruption lit le timer1 et retourne la valeur dans le corps du programme pour traitement ultérieur (on a 20ms pour le faire).

L'entrée étant un trigger de schmitt, la détection se fait autour de 3.5V, soit 1.5V en dessous du Vdd, soit 15µs avant le vrai zéro secteur. L'oscillogramme suivant illustre la durée de la routine interruption au total, avec la sauvegarde et la restitution du contexte, elle dure un peu plus de 25µs.

 

Implantation logicielle

Astuces :



Implantation

Le prototype a été mis au point avec un PIC16F628.

L'alimentaion utilise une capacité de 330nF (soit un courant moyen consommé de 10mA) mais cela devrait fonctionner avec une capacité shunt de 100nF.

L'amorçage triac utilise un transistor pour avoir une capacité en courant assez forte (50mA).

L'analyse de la tension gate, est réalisée par les comparateurs internes du PIC, sur les entrées RA0, RA1, RA2, RA3.

 

 

 

Améliorations

Quelques idées d'amélioration :

 


Références