loading
Not every instructable needs to be extensive or difficult. In fact this low voltage AC switcher for a micro controller is pretty simple. I put it as an instructable just because you dont see many of these circuits and it allows me to share the printdesign I made with others who may just need this circuit. Also, with many circuits one finds on the internet, you are not sure if someone actually built a working version. Well This one works. The design isn't really mine, someone sketched it for me. I might have seperated the  ground from the two, but it works

This circuit can be used to switch a low voltage (12V) AC load with an Arduino or other microcontroller. A positive signal on the entrance will bring T1 into conduction, triggering the Triac via emitter resistor R2. D1 and C1 are just there to provide DC-power to the transistor. R3 will pull the base low. The circuit will work without R3 but it might react erratic: during start up of your nicrocontroller, the pin connected to the circuit might be undefined and switch someting while it is not desired. Also, as negative impulses can trigger a TRIAC, switching from high to low can trigger the triac if R3 is not present.

The Triac should be cooled with a metal profile. remember that the Gate is galvanically connected with the metal housing of the Triac.

WARNING: This is for LOW AC voltage only. Switching a high voltage AC requires use of opto couplers to isolate the High Voltage from the microcontroller.

Notes. I have used an SC141B Triac rather than a TIC206 as I had that around and it is 110 V. max. In a 220 V. country I am not likely going to use that soon for another project. The picture of the mounted PCB does not show the heatsink yet. It is advisable to use a heatsink. The printdesign can be downloaded here. There is space for various size capacitors. Mine seems very big but it is a very old one I still had lying around. You may want to move the position of D1 to make it a bit easier to mount a heatsink. The Diode D1 does not really need to be a 1N4007. The DC part of the circuit does not really need much power. a 1n4148 would be OK, but they have the same price and I had a 1n4007 lying around.
The circuit can be simplified by just using a pin of the arduino to trigger the triac via a resistor. That will probably work for a TIC206 that needs only 5 mA, but other Triacs may need a bit more than is advisable for your arduino.
And here is then the second code : master code <br> <br> <br> <br>// MASTER CODE - Uno gestion lumiere 220V <br> <br>// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <br>// A4 ET A5 doivent etre branch&eacute; ensemble entre les deux arduinos (pour liaison i2c) <br>// DEBRANCHER USB AVANT TOUTE MODIF DES JUMPERS DE COMMUNICATION !!! <br>// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <br> <br> <br>// ***************************************** D&eacute;claration variables globales **************************************** <br>#include // inclu la librairie i2c de communication <br> <br>const int Pin_ZeroCross = 2 ; // Broche qui envoie le signal Zero Cross (a cot&eacute; du Vcc) <br>const int Pin_SIGNAL = 8 ; // Broche allumant le triac de controle 220V <br> int dimming_level = 50 ; // Variable niveau lumiere re&ccedil;u (varie entre 0 et 256) - initialis&eacute; &agrave; 50 arbitrairement pour &eacute;viter blocage <br> int dimming_time = 50 ; // Variable converti &agrave; partir de dimming_level (entre 30 et 128) - initialis&eacute; &agrave; 50 arbitrairement pour &eacute;viter blocage <br>unsigned long T_old = 0 ; // Varaible ancien temps d'acquisition (en us) <br>unsigned long T_new = 0 ; // Variable temps actuel (us) <br>const long Tempo = 30000 ; // Temporisation avant nouvelle acquisition valeur (en us) - modif <br>//****************************************************************************************************************** <br> <br>// ************************************************ FONCTION SETUP ************************************************* <br>void setup(){ <br> Wire.begin(); // Declare l'arduino B en maitre pour com i2c <br> pinMode(Pin_ZeroCross, INPUT); // Declare la broche qui permet de detecter la phase <br> pinMode(Pin_SIGNAL, OUTPUT); // Declare la broche qui permet d'allumer le triac HT <br>}//***************************************************************************************************************** <br> <br>// ************************************************* FONCTION LOOP ************************************************* <br>void loop(){ <br> <br> T_new = micros(); // Enregistre le temps courant (us) <br> if ((T_new - T_old) &gt;= Tempo){ // Verif si il faut rechercher une nouvelle valeur aupres de l'arduino de gestion de niveau lumineux <br> Wire.requestFrom(1, 1); // Demande info ecslave 1, 1 byte <br> while(Wire.available()) { // Des que dispo <br> dimming_level = Wire.read();} // Lecture d&egrave;s que c'est possible <br> T_old = T_new; // Stockage de la nouvelle valeur de temps car valeur acquise <br> } <br> <br> if(dimming_level &lt; 122) { // When light should be fired <br> pulseIn(Pin_ZeroCross, HIGH); // When the HV crossed 0V then <br> digitalWrite(Pin_SIGNAL, LOW); // Triac off <br> int dimming_time = (75*dimming_level); // For 60Hz =&gt; 65 <br> delayMicroseconds(dimming_time); // Off cycle <br> digitalWrite(Pin_SIGNAL, HIGH); // Triac firing <br> delayMicroseconds(10); // Triac On propogation delay (for 60Hz use 8.33) <br> digitalWrite(Pin_SIGNAL, LOW); // Triac Off <br> } <br>}//***************************************************************************************************************** <br>
Thanks for both codes. Using the PulseIn for the zero cross is not something I had thought off. <br>Good thing I understand French :-) <br> <br>For all new readers: the discussion with blacktrooper is not about the 12 Volt dimmer but about another project :-)
Hi, <br> <br>Ok. I will post the code here. <br> <br>The first one is the slave code. <br> <br>Some briefs comments : <br>- there is 5 ultrasonic sensors <br>- the interrupt function have been replaced by the PulseIn function in dimming code <br>- (comments are in french) <br> <br>// SLAVE CODE - Uno de d&eacute;tection <br> <br>// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <br>// A4 ET A5 doivent etre branch&eacute; ensemble entre les deux arduinos (pour liaison i2c) <br>// DEBRANCHER USB AVANT TOUTE MODIF DES JUMPERS DE COMMUNICATION !!! <br>// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <br> <br>// ***************************************** D&eacute;claration variables globales **************************************** <br> #include // inclu la librairie i2c de communication <br> <br> const boolean MODE_LUM_ON = 0 ; // Si 1 alors active toujours la lumi&egrave;re, 0 desactive <br> <br> const boolean CAPTEUR_1 = 1 ; // Si 1 alors detecte le capteur 1 <br> const int Pin_Trig_1 = 2 ; // Broche Trig capteur <br> const int Pin_Echo_1 = 3 ; // Broche Echo capteur <br> <br> const boolean CAPTEUR_2 = 1 ; // Si 1 alors detecte le capteur 2 <br> const int Pin_Trig_2 = 4 ; // Broche Trig capteur <br> const int Pin_Echo_2 = 5 ; // Broche Echo capteur <br> <br> const boolean CAPTEUR_3 = 1 ; // Si 1 alors detecte le capteur 3 <br> const int Pin_Trig_3 = 6 ; // Broche Trig capteur <br> const int Pin_Echo_3 = 7 ; // Broche Echo capteur <br> <br> const boolean CAPTEUR_4 = 1 ; // Si 1 alors detecte le capteur 4 <br> const int Pin_Trig_4 = 8 ; // Broche Trig capteur <br> const int Pin_Echo_4 = 9 ; // Broche Echo capteur <br> <br> const boolean CAPTEUR_5 = 1 ; // Si 1 alors detecte le capteur 5 <br> const int Pin_Trig_5 = 10 ; // Broche Trig capteur <br> const int Pin_Echo_5 = 11 ; // Broche Echo capteur <br> <br> const boolean MODE_MOYENNE = 1 ; // Si 1 alors active une moyenne sur X valeurs, 0 d&eacute;sactive - MODIF <br> const int Nb_val = 5 ; // Nb de valeur sur laquelle faire la moyenne - MODIF <br> int Index = 0 ; // Variable de comptage <br> int Tableau_1[Nb_val] ; // Tableau pour effectuer la moyenne <br> int Tableau_2[Nb_val] ; // Tableau pour effectuer la moyenne <br> int Tableau_3[Nb_val] ; // Tableau pour effectuer la moyenne <br> int Tableau_4[Nb_val] ; // Tableau pour effectuer la moyenne <br> int Tableau_5[Nb_val] ; // Tableau pour effectuer la moyenne <br> int Total_1 ; // Variable de stockage <br> int Total_2 ; // Variable de stockage <br> int Total_3 ; // Variable de stockage <br> int Total_4 ; // Variable de stockage <br> int Total_5 ; // Variable de stockage <br> int Moyenne_1 ; // Variable de stockage <br> int Moyenne_2 ; // Variable de stockage <br> int Moyenne_3 ; // Variable de stockage <br> int Moyenne_4 ; // Variable de stockage <br> int Moyenne_5 ; // Variable de stockage <br> <br> const boolean MODE_RAMPE = 1 ; // Si 1 alors active une rampe lors d'un gap important, 0 d&eacute;sactive <br> const int Delta_adm = 12 ; // Delta admissible entre ancienne boucle et nouvelle - MODIF <br> const int MOD = 1 ; // Vitesse de mont&eacute;e en intensit&eacute; lumineuse - MODIF <br> <br> const boolean MODE_ALEATOIRE = 1 ; // Si 1 alors active l'allumage aleatoire apres periode d'inactivit&eacute;, 0 d&eacute;sactive <br> volatile unsigned long Rand_Numb = 0 ; // Variable de stockage pour aleatoire <br> volatile unsigned long T_act ; // D&eacute;finition variable de stockage du temps du dernier allumage lumi&egrave;re <br> const long T_inact_adm = 20000 ; // D&eacute;finition de la dur&eacute;e d'inactivit&eacute; possible - MODIF <br> const long T_Light_auto_ON_min = 1000 ; // Dur&eacute;e pendant laquelle la lumi&egrave;re doit rester allum&eacute;e au minimum en ms - MODIF <br> const long T_Light_auto_ON_max = 3000 ; // Dur&eacute;e pendant laquelle la lumi&egrave;re doit rester allum&eacute;e au maximum en ms - MODIF <br> volatile long T_Light_auto_ON_mem ; // Dur&eacute;e pendant laquelle la lumi&egrave;re doit rester allum&eacute;e en ms <br> const long T_Light_auto_OFF_min = 8000 ; // Dur&eacute;e pendant laquelle la lumi&egrave;re doit rester &eacute;teinte au minimum en ms - MODIF <br> const long T_Light_auto_OFF_max = 20000 ; // Dur&eacute;e pendant laquelle la lumi&egrave;re doit rester &eacute;teinte au maximum en ms - MODIF <br> volatile long T_Light_auto_OFF_mem ; // Dur&eacute;e pendant laquelle la lumi&egrave;re doit rester &eacute;teinte en ms <br> const int Light_auto_min = 110 ; // Intensit&eacute; lumineuse minimum en mode inactif entre 0 et 255 - MODIF <br> const int Light_auto_max = 70 ; // Intensit&eacute; lumineuse maximum en mode inactif entre 0 et 255 - MODIF <br> volatile int Light_auto_mem ; // Intensit&eacute; lumineuse en mode automatique <br> <br> const int Light_level_min = 128 ; // Entre 30 et 128 -&gt; 30 = allum&eacute; / 128 = eteint <br> const int Light_level_max = 40 ; // Entre 30 et 128 -&gt; 30 = allum&eacute; / 128 = eteint - MODIF <br> int Light_level_1 = Light_level_min ; // Distance correspondante <br> int Light_level_2 = Light_level_min ; // Distance correspondante <br> int Light_level_3 = Light_level_min ; // Distance correspondante <br> int Light_level_4 = Light_level_min ; // Distance correspondante <br> int Light_level_5 = Light_level_min ; // Distance correspondante <br> int Light_level_new = Light_level_min ; // Variable de stockage nouvelle valeur <br> int Light_level_new_1 = Light_level_min ; // Variable de stockage nouvelle valeur <br> int Light_level_new_2 = Light_level_min ; // Variable de stockage nouvelle valeur <br> int Light_level_new_3 = Light_level_min ; // Variable de stockage nouvelle valeur <br> int Light_level_new_4 = Light_level_min ; // Variable de stockage nouvelle valeur <br> int Light_level_new_5 = Light_level_min ; // Variable de stockage nouvelle valeur <br> int Light_level_old = Light_level_min ; // Variable de stockage ancienne valeur <br> int Light_level_i2c = Light_level_min ; // Variable intensit&eacute; lumineuse envoy&eacute;e - initialis&eacute; au seuil min <br> <br> int VAR ; // Variable de stockage temporaire <br> const int T_auto = 16 ; // Dur&eacute;e pendant laquelle la valeur est disponible (en ms) - MODIF <br> <br> int Time_1 ; // Dur&eacute;e du signal <br> int Time_2 ; // Dur&eacute;e du signal <br> int Time_3 ; // Dur&eacute;e du signal <br> int Time_4 ; // Dur&eacute;e du signal <br> int Time_5 ; // Dur&eacute;e du signal <br> const int Max_wait_time = 10000 ; // Correspond au Time d'attente maximum du retour ultrason (en us) - MODIF <br> int P_com = 0 ; // Variable passant a 1 si on interrompt la detection pour communication <br> const int Distance_min = 20 ; // Distance &agrave; partir de laquelle la lumi&egrave;re est au max (en cm) - MODIF <br> const int T_loop = 0 ; // Tempo avant nouvelle boucle acquisition (en ms) <br>//****************************************************************************************************************** <br> <br>// ************************************************ FONCTION SETUP ************************************************* <br>void setup(){ <br> Wire.begin(1); // Definition du numero esclave <br> Wire.onRequest(EVENT); // Definition du programme a lancer &agrave; la reception de la demande de com <br> pinMode(Pin_Trig_1,OUTPUT); // Declaration broche Trig <br> pinMode(Pin_Echo_1,INPUT); // Declaration broche Echo <br> pinMode(Pin_Trig_2,OUTPUT); // Declaration broche Trig <br> pinMode(Pin_Echo_2,INPUT); // Declaration broche Echo <br> pinMode(Pin_Trig_3,OUTPUT); // Declaration broche Trig <br> pinMode(Pin_Echo_3,INPUT); // Declaration broche Echo <br> pinMode(Pin_Trig_4,OUTPUT); // Declaration broche Trig <br> pinMode(Pin_Echo_4,INPUT); // Declaration broche Echo <br> pinMode(Pin_Trig_5,OUTPUT); // Declaration broche Trig <br> pinMode(Pin_Echo_5,INPUT); // Declaration broche Echo <br>}//***************************************************************************************************************** <br> <br>// ************************************************* FONCTION LOOP ************************************************* <br>void loop(){ <br> <br>// LUMIERE TOUJOURS ALLUME <br> if (MODE_LUM_ON == 1) { <br> Light_level_i2c = Light_level_max; <br> goto Endpoint; <br> } <br> <br>// CAPTURE DISTANCE PAR CAPTEUR <br> if (CAPTEUR_1 == 1) { <br> digitalWrite(Pin_Trig_1, HIGH); // Allumage Ultrason <br> delayMicroseconds(10); // Tempo <br> P_com = 0; // reinitialisation variable de verif interruption com pendant detection <br> digitalWrite(Pin_Trig_1, LOW); // Extinction Ultrason <br> Time_1 = pulseIn(Pin_Echo_1, HIGH, Max_wait_time); // R&eacute;cup&egrave;re signal par broche LECTURE en us <br> if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection <br> if(Time_1 &gt;= Max_wait_time){ // Condition si le Time est au max <br> Light_level_1 = Light_level_min;} // =&gt; alors ne pas allumer <br> else if (Time_1 &lt;= 0) { // Condition si le Time est nul <br> Light_level_1 = Light_level_min;} // =&gt; alors ne pas allumer <br> else{ // Dans tous les autres cas <br> Light_level_1 = map(Time_1 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3 <br> } <br> } <br> <br> if (CAPTEUR_2 == 1) { <br> digitalWrite(Pin_Trig_2, HIGH); // Allumage Ultrason <br> delayMicroseconds(10); // Tempo <br> P_com = 0; // reinitialisation variable de verif interruption com pendant detection <br> digitalWrite(Pin_Trig_2, LOW); // Extinction Ultrason <br> Time_2 = pulseIn(Pin_Echo_2, HIGH, Max_wait_time); // R&eacute;cup&egrave;re signal par broche LECTURE en us <br> if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection <br> if(Time_2 &gt;= Max_wait_time){ // Condition si le Time est au max <br> Light_level_2 = Light_level_min;} // =&gt; alors ne pas allumer <br> else if (Time_2 &lt;= 0) { // Condition si le Time est nul <br> Light_level_2 = Light_level_min;} // =&gt; alors ne pas allumer <br> else{ // Dans tous les autres cas <br> Light_level_2 = map(Time_2 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3 <br> } <br> } <br> <br> if (CAPTEUR_3 == 1) { <br> digitalWrite(Pin_Trig_3, HIGH); // Allumage Ultrason <br> delayMicroseconds(10); // Tempo <br> P_com = 0; // reinitialisation variable de verif interruption com pendant detection <br> digitalWrite(Pin_Trig_3, LOW); // Extinction Ultrason <br> Time_3 = pulseIn(Pin_Echo_3, HIGH, Max_wait_time); // R&eacute;cup&egrave;re signal par broche LECTURE en us <br> if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection <br> if(Time_3 &gt;= Max_wait_time){ // Condition si le Time est au max <br> Light_level_3 = Light_level_min;} // =&gt; alors ne pas allumer <br> else if (Time_3 &lt;= 0) { // Condition si le Time est nul <br> Light_level_3 = Light_level_min;} // =&gt; alors ne pas allumer <br> else{ // Dans tous les autres cas <br> Light_level_3 = map(Time_3 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3 <br> } <br> } <br> <br> if (CAPTEUR_4 == 1) { <br> digitalWrite(Pin_Trig_4, HIGH); // Allumage Ultrason <br> delayMicroseconds(10); // Tempo <br> P_com = 0; // reinitialisation variable de verif interruption com pendant detection <br> digitalWrite(Pin_Trig_4, LOW); // Extinction Ultrason <br> Time_4 = pulseIn(Pin_Echo_4, HIGH, Max_wait_time); // R&eacute;cup&egrave;re signal par broche LECTURE en us <br> if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection <br> if(Time_4 &gt;= Max_wait_time){ // Condition si le Time est au max <br> Light_level_4 = Light_level_min;} // =&gt; alors ne pas allumer <br> else if (Time_4 &lt;= 0) { // Condition si le Time est nul <br> Light_level_4 = Light_level_min;} // =&gt; alors ne pas allumer <br> else{ // Dans tous les autres cas <br> Light_level_4 = map(Time_4 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3 <br> } <br> } <br> <br> if (CAPTEUR_5 == 1) { <br> digitalWrite(Pin_Trig_5, HIGH); // Allumage Ultrason <br> delayMicroseconds(10); // Tempo <br> P_com = 0; // reinitialisation variable de verif interruption com pendant detection <br> digitalWrite(Pin_Trig_5, LOW); // Extinction Ultrason <br> Time_5 = pulseIn(Pin_Echo_5, HIGH, Max_wait_time); // R&eacute;cup&egrave;re signal par broche LECTURE en us <br> if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection <br> if(Time_5 &gt;= Max_wait_time){ // Condition si le Time est au max <br> Light_level_5 = Light_level_min;} // =&gt; alors ne pas allumer <br> else if (Time_5 &lt;= 0) { // Condition si le Time est nul <br> Light_level_5 = Light_level_min;} // =&gt; alors ne pas allumer <br> else{ // Dans tous les autres cas <br> Light_level_5 = map(Time_5 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3 <br> } <br> } <br> <br>// MOYENNE <br> if (MODE_MOYENNE == 1) { <br> Total_1 = Total_1 - Tableau_1[Index]; <br> Tableau_1[Index] = Light_level_1; <br> Total_1 = Total_1 + Tableau_1[Index]; <br> Moyenne_1 = Total_1 / Nb_val; <br> Light_level_new_1 = Moyenne_1; <br> <br> Total_2 = Total_2 - Tableau_2[Index]; <br> Tableau_2[Index] = Light_level_2; <br> Total_2 = Total_2 + Tableau_2[Index]; <br> Moyenne_2 = Total_2 / Nb_val; <br> Light_level_new_2 = Moyenne_2; <br> <br> Total_3 = Total_3 - Tableau_3[Index]; <br> Tableau_3[Index] = Light_level_3; <br> Total_3 = Total_3 + Tableau_3[Index]; <br> Moyenne_3 = Total_3 / Nb_val; <br> Light_level_new_3 = Moyenne_3; <br> <br> Total_4 = Total_4 - Tableau_4[Index]; <br> Tableau_4[Index] = Light_level_4; <br> Total_4 = Total_4 + Tableau_4[Index]; <br> Moyenne_4 = Total_4 / Nb_val; <br> Light_level_new_4 = Moyenne_4; <br> <br> Total_5 = Total_5 - Tableau_5[Index]; <br> Tableau_5[Index] = Light_level_5; <br> Total_5 = Total_5 + Tableau_5[Index]; <br> Moyenne_5 = Total_5 / Nb_val; <br> Light_level_new_5 = Moyenne_5; <br> <br> Index = Index + 1; <br> if (Index &gt;= Nb_val) {Index = 0;} <br> } <br> else if (MODE_MOYENNE == 0) { <br> Light_level_new_1 = Light_level_1; // Ecrasement de l'ancienne valeur &agrave; envoyer <br> Light_level_new_2 = Light_level_2; // Ecrasement de l'ancienne valeur &agrave; envoyer <br> Light_level_new_3 = Light_level_3; // Ecrasement de l'ancienne valeur &agrave; envoyer <br> Light_level_new_4 = Light_level_4; // Ecrasement de l'ancienne valeur &agrave; envoyer <br> Light_level_new_5 = Light_level_5; // Ecrasement de l'ancienne valeur &agrave; envoyer <br> } <br> <br>// COMPARAISON DISTANCE <br> Light_level_new = min(128,Light_level_new_1); <br> Light_level_new = min(Light_level_new,Light_level_new_2); <br> Light_level_new = min(Light_level_new,Light_level_new_3); <br> Light_level_new = min(Light_level_new,Light_level_new_4); <br> Light_level_new = min(Light_level_new,Light_level_new_5); <br> <br>// RAMPE <br> if (MODE_RAMPE == 1) { <br> if ((abs(Light_level_old - Light_level_new)) &gt; Delta_adm) { <br> if (Light_level_old &lt; Light_level_new) { <br> for (Light_level_i2c = Light_level_old ; Light_level_i2c &lt;= Light_level_new; Light_level_i2c = Light_level_i2c + MOD) { <br> delay(T_auto/3); <br> } <br> } <br> else if (Light_level_old &gt; Light_level_new) { <br> for (Light_level_i2c = Light_level_old ; Light_level_i2c &gt;= Light_level_new ; Light_level_i2c = Light_level_i2c - MOD) { <br> delay(T_auto/3); <br> } <br> } <br> } <br> else { <br> Light_level_i2c = Light_level_new; <br> } <br> Light_level_old = Light_level_new; <br> } <br> else if (MODE_RAMPE == 0) { <br> Light_level_i2c = Light_level_new; <br> } <br> <br>// ALEATOIRE <br> if (MODE_ALEATOIRE == 1) { <br> if (Light_level_i2c &lt; Light_level_min) { // Cas valeur diff&eacute;rente de 0 <br> T_act = millis(); // M&eacute;morisation temps actuel <br> if (Rand_Numb &gt; 10000) {Rand_Numb = 0;} // Remet a zero la variable de stockage pour eviter debordement <br> Rand_Numb = Rand_Numb + 1; // Incrementation compteur <br> randomSeed(Rand_Numb); // Modifie le noyau de la fonction aleatoire <br> T_Light_auto_OFF_mem = random(T_Light_auto_OFF_min, T_Light_auto_OFF_max);} // M&eacute;morisation valeur premi&egrave;re attente <br> else { // Increment <br> if ((millis() - T_act) &gt; T_Light_auto_OFF_mem) { // Temporisation inactif d&eacute;pass&eacute; <br> Light_auto_mem = random(Light_auto_max, Light_auto_min); // Randomisation valeur intensit&eacute; lumineuse <br> T_Light_auto_ON_mem = random(T_Light_auto_ON_min, T_Light_auto_ON_max); // Randomisation dur&eacute;e pendant laquelle la lumi&egrave;re est allum&eacute;e <br> T_Light_auto_OFF_mem = random(T_Light_auto_OFF_min, T_Light_auto_OFF_max); // Randomisation dur&eacute;e d'attente jusqu'au prochain allumage <br> for (VAR = Light_level_min; VAR &gt; Light_auto_mem; VAR = VAR--) { // Rampe mont&eacute;e lumi&egrave;re <br> Light_level_i2c = VAR; // Allumage <br> delay(T_auto); // Tempo <br> } <br> delay(T_Light_auto_ON_mem); <br> for (VAR = Light_auto_mem; VAR &lt; Light_level_min; VAR = VAR++) { // Rampe descente lumi&egrave;re <br> Light_level_i2c = VAR; // Allumage <br> delay(T_auto); // Tempo <br> } <br> T_act = millis(); // M&eacute;morisation temps actuel <br> } <br> } <br> } <br> <br>// FIN <br> Endpoint: <br> <br> delay(T_loop); // Ralenti la boucle d'acquisition <br> <br>}//********************************************************************************************************************* <br> <br>// ******************************************** FONCTION COMMUNICATION ************************************************* <br>void EVENT(){ <br> Wire.write(Light_level_i2c); // Commande ex&eacute;cut&eacute;e lorsque le Master le demande <br> P_com = 1; <br>}//********************************************************************************************************************* <br> <br>
Done !<br>Actually it seems the LED is not responsible. I have to say I didn't want to unsolder so I tried other ways.<br>I took an other Uno and divided tasks. The first Uno, lets say &quot;A&quot;, is connected in i2c slave and has to measure the distance and calculate the corresponding dimming level.<br>The second uno, then the &quot;B&quot; one, is the master reader. It asks every 40ms an update of the dimming level.<br><br>Then it works!<br><br>Ok it sounds easy but I had some issues with the dimming level which has to , i don't know why, always bigger than 30 instead of 0 et smaller than 122.<br><br>Besides, I have to say I do not use anymore interrupt function which is pretty tricky. I doesn't recognise some function. Then i prefered to use pulseIn in my code.<br><br>If some one is interested by the code, i can provide it !<br><br>Thank you diy_bloke for your help !
Actually, it has always worked fine for me with the LED. I only know of one person who experienced problems nut I understood he had an LED with a high voltage drop. <br>As It is beyond my control what LED people use and I like it to be reproducable as much as possible without problems, I now advise to replace the LED by a resistor
Thanks. Obviously I am interested in your code. <br>I presume you use the PulseIn for the distance sensor, not for the Triac :-)
Hi, <br>Geat instructable ! <br> <br>Do you have an idea of a circuit which could allow to dim a 220V AC light bulb with a PWM signal without using the interrupt function on arduino ? <br>I'm desperately looking for it on the web but nothing ! <br> <br>Thanks in advance for your help <br> <br> <br>Chris
Well, the circuit in itself does not have that much to do with the interrupt use on an arduino. <br>Check this circuit: http://www.instructables.com/id/Arduino-controlled-light-dimmer-The-circuit/ <br>The software provided for that uses an interrupt coz that is easiest, but you can get the same results by polling the pin
It's exactly this circuit I tried ! <br>I don't understand what do you mean by &quot;polling the pin&quot;. <br>Sorry, I'm a beginner ! <br> <br>PS: I'm trying to dim a lamp according to the distance I measure with a subsonic sensor HC-SR04. But the interrupt function for the circuit &quot;breaks&quot; the measurement which is time critical. I'm I clear ?
I think you are clear but it still should be possible to use more than one interrupt. <br>Do you mean that the interrupt function for the dimmer breaks the critical timing of yr HC SR04 timer? <br>Perhaps the CLI and SEi instructions that clear and set interrupts can be used to temporarily switch off yr interrupts while you are doing yr time ctritical calculations <br> <br>'Polling' is to have your software check the status of a pin continuously. <br>Without knowing the exact software you are using for your sensor, it is hard to give more advice
perhaps this is also of some help to you: http://forum.arduino.cc/index.php?topic=155863.0
Yes it is what I mean. I have then wrong values and finally the lamp is flickering. Here is my code : <br> <br> <br>//*************************************** DECLARATION VARIABLES *************************************** <br>int Signal_pin = 3; // Output to Opto Triac pin <br>int Sensor_output_pin = 8; // Broche Trig pour Ultrason <br>int Sensor_input_pin = 9; // Broche Echo pour Ultrason <br>int dimming_level = 128; // Dimming level (0-128) 0 = ON, 128 = OFF <br>//***************************************************************************************************** <br> <br>//***************************************************************************************************** <br>void setup() { <br> Serial.begin(115200); // Open USB port <br> pinMode(Signal_pin, OUTPUT); // Set AC Load pin as output <br> pinMode(Sensor_output_pin, OUTPUT); // Set the trig pin for subsonic sensor <br> pinMode(Sensor_input_pin, INPUT); // Set the echo pin for subsonic sensor <br> <br> attachInterrupt(0, zero_cross, RISING); // Choose the zero cross interrupt # from the table above <br>}//**************************************************************************************************** <br> <br>//***************************************************************************************************** <br>void zero_cross() { <br> // Function to be fired at the zero crossing to dim the light <br> // The interrupt function must take no parameters and return nothing <br> // Firing angle calculation : 1 full 50Hz wave =1/50=20ms <br> // Every zerocrossing thus: <br> // For 50Hz -&gt; 20ms for 1 cycle <br> // -&gt; 10ms for 1/2 cycle For 60Hz =&gt; 8.33ms <br> // 10ms = 10000us <br> // (10000us - 10us) / 128 = 75 (Approx) For 60Hz =&gt; 65 <br>int dimming_time = (75*dimming_level); // For 60Hz =&gt;65 <br>delayMicroseconds(dimming_time); // Off cycle <br>digitalWrite(Signal_pin, HIGH); // Triac firing <br>delayMicroseconds(10); // Triac On propogation delay (for 60Hz use 8.33) <br>digitalWrite(Signal_pin, LOW); // Triac Off <br>}//**************************************************************************************************** <br> <br>//***************************************************************************************************** <br>void loop() { <br> digitalWrite(Sensor_output_pin,HIGH); // Subsonic signal send <br> delayMicroseconds(10); // Wait <br> digitalWrite(Sensor_output_pin,LOW); // Subsonic signal pin put to LOW <br> int Temps = pulseIn(Sensor_input_pin,HIGH,12000); // Wait and see if there is a signal <br> int dimming_level = map(Temps, 0, 12000, 30, 128); // Calculate the corresponding dimming level <br> Serial.println(dimming_level); // Send from USB port the value <br>}//****************************************************************************************************
if you use the program that i supplied, so without yr distance meter. is the circuit then functioning normally? or is it flickering too then? in that case you may first want to try to replace the LED by another 220Ohm resistor. That means there is NO LED anymore (that has a voltage drop) and only a resistance of 440 ohms. As the voltage drop over the LED is sometimes a bit unpredictable. <br> <br>From your code it seems that you are still using the interrupt for the zero crossing and just a write/read of yr sensor. That really should not be time critical I think so try to get rid of the LED first. <br> <br>Also, the PulseIn function is reported to have timing issues, some people have solved problems by lowering the baudrate. <br>At the other hand, assuming my math is correct, at 9600 baud, it's going to take about 5.5mS (5500uS) to send out four digits and a carriage return, so the serial output is throwing off the results. <br> <br>You let yr PulseIn wait for 12mS. Not sure if that is long enough for your sensor. <br>I am not sure if the 12000 (for the timing) in yr PulseIn and yr Map command are just by coincidence the same, but I guess the max value you expect from yr PulseIn=12000 and you want to wait 12000 uSecs for the signal. <br> <br>My best advice for now: get rid of the serial printline statement and if that does not help replace the LED bij a 220 ohm resistor
Hi, <br> <br>Sorry for the late reply. <br>I will try all your new ways in the week I hope and then I'll give you my feedback. <br> <br>Just for now, I know the measuring cycle seems to be correct because if I try it without the interrupt function, all the values are OK and there is now big gap. <br> <br>I'm sooooo happy you try to help me ! <br>Thank you very much
Also... are you sure you trigger your sensor in the right way? You write a HIGH and a LOW with 10mS waiting time, whereas the correct/advised triggering would be: <br>digitalWrite(pingPin, LOW); <br> delayMicroseconds(2); <br> digitalWrite(pingPin, HIGH); <br> delayMicroseconds(5); <br> digitalWrite(pingPin, LOW); <br> <br>or even : <br>digitalWrite(pingPin, LOW); <br> delayMicroseconds(2); <br> digitalWrite(pingPin, HIGH); <br> delayMicroseconds(10); <br> digitalWrite(pingPin, LOW); <br> <br>You are aware there is a library for the HC SR04 right?

About This Instructable

5,964 views

14 favorites

License:

Bio: I am a physician by trade. After a career in the pharmeceutical world I decided to take it a bit slower and do things I ... More »
More by diy_bloke: Reading the BMP180 Pressure sensor with an Attiny85 and add a DHT11 too Using 433MHz Remote Controlled Switches on Arduino Make an Android App to control via Bluetooth an Arduino Controlling your house via RF, all with AppInventor
Add instructable to: