le code:
/*
GRADATEURS 230V (8 canaux, potentionnellement plus)
par Gromain59
Partie materielle:
- triac piloté par une sortie digitale via un optocoupleur
- opto-coupleur AC pour la détection du passage à zéro de la phase
Partie logicielle:
- une interruption materielle sur l'entrée 2 lors du passage à zéro de la phase
- une interruption logicielle qui intervient entre 100µs et 1400µs.
=> l'intervalle d'interruption est variable afin d'obtenir une courbe de luminosité linéaire selon la consigne, du fait de la forme sinusoïdale du signal.
on a donc:
1. detection du passage à zero sur l'entree 2
2. execution de detection_zero(): traitement des canaux avec une consigne de 0% et de 100%
3. desactivation d'interruption materielle, activation de l'interruption logicielle sur la base de retard[0]
4. interruption au bout de retard[c2] µs (c2=0)
5. execution de controle_canaux()
=> incrementation de l'index c2
et si c2 est supérieur à 49, alors c'est le dernier cycle
=> extinction de tous les canaux
=> activation de l'interruption materielle
sinon:
=> activation sorties des canaux ayant pour consigne 98% (soit un retard de 469µs) ou si
=> reconfiguration de l'interruption temporelle avec un nouveau retard, retard[c2]
Pour modifier la consigne d'un canal, il faut envoyer via le serial monitor une trame de la forme:
" D/0/45/F"
=> un espace
=> "D" pour indiquer le début de la trame
=> "/" comme séparateur
=> le canal concerné (de 0 à 7 ici)
=> "/" comme séparateur
=> le niveau souhaité (de 0% à 100%)
=> "/" comme séparateur
=> "F" pour indiquer la fin de la trame
Une fois la trame recu, la fonction sscanf se charge de recuperer les donnees.
On convertit la consigne recu en niveau (de 0 à 50 niveaux)
ressources:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230333861/30 pour les premiers essais
http://www.hoelscher-hi.de/hendrik/english/dimmer.htm pour la partie electronique
http://www.abcelectronique.com/bigonoff/domocan.php?par=3efd4 pour la partie electronique et soft (PIC)
le forum arduino
*/
#include <TimerOne.h> // pour l'interruption temps http://www.arduino.cc/playground/Code/Timer1
#include <stdio.h> // pour le traitement de la trame contenant le changement de consigne
//valeur de timeout pour la reception de la trame
int tps_max_lecture = 200; //lecture d'un code, compteur max entre tous les caractères d'un code
int tps_max_carte = 1000; //compteur max entre reception d'un caractère
long retard[]= {
1469 , // 98 % 1 225,3V retard / zéro = 1469 ms
287 , // 96 % 2 222,7V retard / zéro = 1867 ms
234 , // 94 % 3 220,6V retard / zéro = 2154 ms
201 , // 92 % 4 218,2V retard / zéro = 2388 ms
180 , // 90 % 5 215,4V retard / zéro = 2589 ms
164 , // 88 % 6 213,3V retard / zéro = 2769 ms
152 , // 86 % 7 210,8V retard / zéro = 2933 ms
143 , // 84 % 8 208V retard / zéro = 3085 ms
135 , // 82 % 9 205,7V retard / zéro = 3228 ms
129 , // 80 % 10 202,8V retard / zéro = 3363 ms
124 , // 78 % 11 200,5V retard / zéro = 3492 ms
120 , // 76 % 12 197,6V retard / zéro = 3616 ms
116 , // 74 % 13 195,2V retard / zéro = 3736 ms
112 , // 72 % 14 192,4V retard / zéro = 3852 ms
110 , // 70 % 15 189,6V retard / zéro = 3964 ms
108 , // 68 % 16 186,8V retard / zéro = 4074 ms
106 , // 66 % 17 184V retard / zéro = 4182 ms
105 , // 64 % 18 180,9V retard / zéro = 4288 ms
103 , // 62 % 19 178,1V retard / zéro = 4393 ms
102 , // 60 % 20 175,1V retard / zéro = 4496 ms
101 , // 58 % 21 172,1V retard / zéro = 4598 ms
101 , // 56 % 22 168,9V retard / zéro = 4699 ms
100 , // 54 % 23 166,2V retard / zéro = 4800 ms
100 , // 52 % 24 162,6V retard / zéro = 4900 ms
100 , // 50 % 25 159,3V retard / zéro = 5000 ms
101 , // 48 % 26 155,8V retard / zéro = 5100 ms
100 , // 46 % 27 152,6V retard / zéro = 5201 ms
101 , // 44 % 28 149,1V retard / zéro = 5301 ms
102 , // 42 % 29 145,3V retard / zéro = 5402 ms
103 , // 40 % 30 141,8V retard / zéro = 5504 ms
105 , // 38 % 31 138V retard / zéro = 5607 ms
106 , // 36 % 32 133,8V retard / zéro = 5712 ms
108 , // 34 % 33 130V retard / zéro = 5818 ms
110 , // 32 % 34 126V retard / zéro = 5926 ms
112 , // 30 % 35 121,7V retard / zéro = 6036 ms
116 , // 28 % 36 117,1V retard / zéro = 6148 ms
120 , // 26 % 37 112,6V retard / zéro = 6264 ms
124 , // 24 % 38 107,7V retard / zéro = 6384 ms
129 , // 22 % 39 102,4V retard / zéro = 6508 ms
135 , // 20 % 40 97,2V retard / zéro = 6637 ms
143 , // 18 % 41 92V retard / zéro = 6772 ms
152 , // 16 % 42 85,7V retard / zéro = 6915 ms
164 , // 14 % 43 79,4V retard / zéro = 7067 ms
180 , // 12 % 44 72,8V retard / zéro = 7231 ms
201 , // 10 % 45 64,8V retard / zéro = 7411 ms
234 , // 8 % 46 56,4V retard / zéro = 7612 ms
286 , // 6 % 47 46V retard / zéro = 7846 ms
399 , // 4 % 48 32,4V retard / zéro = 8132 ms
500//1469 , // 2 % 49 0V retard / zéro = 8531 ms
};
int consigne[]= { // consigne niveau de canal (0=100%, 50=0%)
0, // sortie 0
0, // sortie 1
0, // sortie 2
0, // sortie 3
0, // sortie 4
0, // sortie 5
0, // sortie 6
0, // sortie 7
};
int sortie[]= { //affecte une pin pour chaque canal.
8, // sortie 0
13, // sortie 1
0, // sortie 2
0, // sortie 3
0, // sortie 4
0, // sortie 5
0, // sortie 6
0, // sortie 7
};
volatile int c1=0; // index c1 pour lecture des données de chaque canal (n° pin, consigne)
volatile int c2=0; // index c2 nombre de passage dans la boucle de controle retard de phase (49 passages)
// definition des macros pour piloter les sorties
#define allume(index) (digitalWrite(sortie[index], HIGH))
#define eteint(index) (digitalWrite(sortie[index], LOW))
void setup() { // Debut du setup
// initialise la liaison série
Serial.begin(9600);
// initialise les sorties des canaux (triacs)
for (c1=0; c1 <= 7; c1++){ // on parcourt les 8 canaux pour les configurer
pinMode(sortie[c1], OUTPUT); // on associe chaque canal a une pin, qu'on configure en sortie digitale
eteint(sortie[c1]); // et on éteint la sortie
}
Serial.println("GRADATEUR 8 CANAUX v0.1");
Serial.println("TRAME ATTENDUE: <espace>'D'/'numero de sortie'/'consigne'/'F'");
// initialise l'interruption de temps Timer1
Timer1.initialize(); // Initialize TimerOne library for the freq we need
// Attache l'interruption 0 à la pin 2 pour la detection du passage a zero (Zero Cross Detection)
attachInterrupt(0, detection_zero, FALLING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
} // Fin du setup
void detection_zero() { // Fonction associee à l'interruption 0
detachInterrupt(0); // on desactive l'interruption zero crossing
c2=0;
for (c1=0; c1 <= 7; c1++){ // on parcourt les 8 sorties pour verifier leur consigne
if (consigne[c1]>=49){ // si consigne 0%
eteint(c1); // alors on éteint
}
if (consigne[c1]<=0){ // si consigne 100%
allume(c1); // alors on allume
}
}
Timer1.attachInterrupt(controle_canaux, retard[c2]); // on attache l'interruption temporelle
} // Fin de detection_zero
void controle_canaux() { // ici on verifie si le triac doit etre amorce
c2=c2++;
attachInterrupt(0, detection_zero, FALLING); // on attache une interruption sur la pin 2 (interruption 0)
Timer1.detachInterrupt(); // on detache l'interruption temporelle
if (c2>=49){ // si dernier cycle alors
for (c1=0; c1 <= 7; c1++){ // on parcourt les 8 sorties
eteint(c1); // et on eteint le canal en vue du prochain cycle
}
}
else { // sinon
Timer1.attachInterrupt(controle_canaux, retard[c2]); // on attache une interruption temporelle
for (c1=0; c1 <= 7; c1++){ // on parcourt les 8 sorties pour verifier leur consigne
if (consigne[c1]==c2) // si consigne est egale a la valeur traitee (n° de passage dans la boucle)
{ allume(c1);} // alors on allume le canal
}
} // End controle_canaux function
}
void loop() { // Main Loop
int n = 0;
if(Serial.available()>0){
n = lecture();
}
}
int lecture(){ // lecture d'une trame type: " D/aaa/bbb/F"
// ou "D" caractere de debut de trame
// ou "aaaa" n° de sortie dont la consigne est a modifier
// ou "bbbb" nouvelle consigne de la sortie (entre 0 et 100%)
char buf[15]=" ";
int timeout=0;
int i=0;
int n1=0;
int n2=0;
char c1,c2;
while(Serial.available()>0){
if(i!=14){
buf[i] = Serial.read();
i++;
}
timeout++;
if(timeout>tps_max_lecture)
{Serial.println("T1");
return -1;
}
if(timeout> tps_max_lecture)
{Serial.println("T2");
return -2;
}
}
sscanf(buf, "%c/%d/%d/%c", &c1, &n1, &n2, &c2); //decodage trame
if (c1=='D' && c2 == 'F'){ // on verifie si la trame commence bien par D et termine bien par F
int nouv_cons=n2; // on stocke la nouvelle valeur pour la travailler ensuite
nouv_cons=constrain(nouv_cons, 0, 100); // on borne la nouvelle valeur entre 0 et 100%
Serial.print("sortie ");
Serial.print(n1);
Serial.print(" , nouvelle consigne de: ");
Serial.print(nouv_cons);
Serial.print(" % soit index retard: ");
consigne[n1]= (50-(nouv_cons/2)); // on convertit la valeur 0-100% en n° de retard de phase
Serial.println(consigne[n1]);
}
else // si caractere de debut ou de fin de trame non reconnu
{Serial.println("code inconnu");}
return i;
}
[/code