Instructables

Simple Low Voltage AC switching with a microcontroller

Picture of Simple Low Voltage AC switching  with a microcontroller
AC_laagspanning.JPG
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



// MASTER CODE - Uno gestion lumiere 220V

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// A4 ET A5 doivent etre branché ensemble entre les deux arduinos (pour liaison i2c)
// DEBRANCHER USB AVANT TOUTE MODIF DES JUMPERS DE COMMUNICATION !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


// ***************************************** Déclaration variables globales ****************************************
#include // inclu la librairie i2c de communication

const int Pin_ZeroCross = 2 ; // Broche qui envoie le signal Zero Cross (a coté du Vcc)
const int Pin_SIGNAL = 8 ; // Broche allumant le triac de controle 220V
int dimming_level = 50 ; // Variable niveau lumiere reçu (varie entre 0 et 256) - initialisé à 50 arbitrairement pour éviter blocage
int dimming_time = 50 ; // Variable converti à partir de dimming_level (entre 30 et 128) - initialisé à 50 arbitrairement pour éviter blocage
unsigned long T_old = 0 ; // Varaible ancien temps d'acquisition (en us)
unsigned long T_new = 0 ; // Variable temps actuel (us)
const long Tempo = 30000 ; // Temporisation avant nouvelle acquisition valeur (en us) - modif
//******************************************************************************************************************

// ************************************************ FONCTION SETUP *************************************************
void setup(){
Wire.begin(); // Declare l'arduino B en maitre pour com i2c
pinMode(Pin_ZeroCross, INPUT); // Declare la broche qui permet de detecter la phase
pinMode(Pin_SIGNAL, OUTPUT); // Declare la broche qui permet d'allumer le triac HT
}//*****************************************************************************************************************

// ************************************************* FONCTION LOOP *************************************************
void loop(){

T_new = micros(); // Enregistre le temps courant (us)
if ((T_new - T_old) >= Tempo){ // Verif si il faut rechercher une nouvelle valeur aupres de l'arduino de gestion de niveau lumineux
Wire.requestFrom(1, 1); // Demande info ecslave 1, 1 byte
while(Wire.available()) { // Des que dispo
dimming_level = Wire.read();} // Lecture dès que c'est possible
T_old = T_new; // Stockage de la nouvelle valeur de temps car valeur acquise
}

if(dimming_level < 122) { // When light should be fired
pulseIn(Pin_ZeroCross, HIGH); // When the HV crossed 0V then
digitalWrite(Pin_SIGNAL, LOW); // Triac off
int dimming_time = (75*dimming_level); // For 60Hz => 65
delayMicroseconds(dimming_time); // Off cycle
digitalWrite(Pin_SIGNAL, HIGH); // Triac firing
delayMicroseconds(10); // Triac On propogation delay (for 60Hz use 8.33)
digitalWrite(Pin_SIGNAL, LOW); // Triac Off
}
}//*****************************************************************************************************************
diy_bloke (author)  blacktrooper21 year ago
Thanks for both codes. Using the PulseIn for the zero cross is not something I had thought off.
Good thing I understand French :-)

For all new readers: the discussion with blacktrooper is not about the 12 Volt dimmer but about another project :-)
Hi,

Ok. I will post the code here.

The first one is the slave code.

Some briefs comments :
- there is 5 ultrasonic sensors
- the interrupt function have been replaced by the PulseIn function in dimming code
- (comments are in french)

// SLAVE CODE - Uno de détection

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// A4 ET A5 doivent etre branché ensemble entre les deux arduinos (pour liaison i2c)
// DEBRANCHER USB AVANT TOUTE MODIF DES JUMPERS DE COMMUNICATION !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// ***************************************** Déclaration variables globales ****************************************
#include // inclu la librairie i2c de communication

const boolean MODE_LUM_ON = 0 ; // Si 1 alors active toujours la lumière, 0 desactive

const boolean CAPTEUR_1 = 1 ; // Si 1 alors detecte le capteur 1
const int Pin_Trig_1 = 2 ; // Broche Trig capteur
const int Pin_Echo_1 = 3 ; // Broche Echo capteur

const boolean CAPTEUR_2 = 1 ; // Si 1 alors detecte le capteur 2
const int Pin_Trig_2 = 4 ; // Broche Trig capteur
const int Pin_Echo_2 = 5 ; // Broche Echo capteur

const boolean CAPTEUR_3 = 1 ; // Si 1 alors detecte le capteur 3
const int Pin_Trig_3 = 6 ; // Broche Trig capteur
const int Pin_Echo_3 = 7 ; // Broche Echo capteur

const boolean CAPTEUR_4 = 1 ; // Si 1 alors detecte le capteur 4
const int Pin_Trig_4 = 8 ; // Broche Trig capteur
const int Pin_Echo_4 = 9 ; // Broche Echo capteur

const boolean CAPTEUR_5 = 1 ; // Si 1 alors detecte le capteur 5
const int Pin_Trig_5 = 10 ; // Broche Trig capteur
const int Pin_Echo_5 = 11 ; // Broche Echo capteur

const boolean MODE_MOYENNE = 1 ; // Si 1 alors active une moyenne sur X valeurs, 0 désactive - MODIF
const int Nb_val = 5 ; // Nb de valeur sur laquelle faire la moyenne - MODIF
int Index = 0 ; // Variable de comptage
int Tableau_1[Nb_val] ; // Tableau pour effectuer la moyenne
int Tableau_2[Nb_val] ; // Tableau pour effectuer la moyenne
int Tableau_3[Nb_val] ; // Tableau pour effectuer la moyenne
int Tableau_4[Nb_val] ; // Tableau pour effectuer la moyenne
int Tableau_5[Nb_val] ; // Tableau pour effectuer la moyenne
int Total_1 ; // Variable de stockage
int Total_2 ; // Variable de stockage
int Total_3 ; // Variable de stockage
int Total_4 ; // Variable de stockage
int Total_5 ; // Variable de stockage
int Moyenne_1 ; // Variable de stockage
int Moyenne_2 ; // Variable de stockage
int Moyenne_3 ; // Variable de stockage
int Moyenne_4 ; // Variable de stockage
int Moyenne_5 ; // Variable de stockage

const boolean MODE_RAMPE = 1 ; // Si 1 alors active une rampe lors d'un gap important, 0 désactive
const int Delta_adm = 12 ; // Delta admissible entre ancienne boucle et nouvelle - MODIF
const int MOD = 1 ; // Vitesse de montée en intensité lumineuse - MODIF

const boolean MODE_ALEATOIRE = 1 ; // Si 1 alors active l'allumage aleatoire apres periode d'inactivité, 0 désactive
volatile unsigned long Rand_Numb = 0 ; // Variable de stockage pour aleatoire
volatile unsigned long T_act ; // Définition variable de stockage du temps du dernier allumage lumière
const long T_inact_adm = 20000 ; // Définition de la durée d'inactivité possible - MODIF
const long T_Light_auto_ON_min = 1000 ; // Durée pendant laquelle la lumière doit rester allumée au minimum en ms - MODIF
const long T_Light_auto_ON_max = 3000 ; // Durée pendant laquelle la lumière doit rester allumée au maximum en ms - MODIF
volatile long T_Light_auto_ON_mem ; // Durée pendant laquelle la lumière doit rester allumée en ms
const long T_Light_auto_OFF_min = 8000 ; // Durée pendant laquelle la lumière doit rester éteinte au minimum en ms - MODIF
const long T_Light_auto_OFF_max = 20000 ; // Durée pendant laquelle la lumière doit rester éteinte au maximum en ms - MODIF
volatile long T_Light_auto_OFF_mem ; // Durée pendant laquelle la lumière doit rester éteinte en ms
const int Light_auto_min = 110 ; // Intensité lumineuse minimum en mode inactif entre 0 et 255 - MODIF
const int Light_auto_max = 70 ; // Intensité lumineuse maximum en mode inactif entre 0 et 255 - MODIF
volatile int Light_auto_mem ; // Intensité lumineuse en mode automatique

const int Light_level_min = 128 ; // Entre 30 et 128 -> 30 = allumé / 128 = eteint
const int Light_level_max = 40 ; // Entre 30 et 128 -> 30 = allumé / 128 = eteint - MODIF
int Light_level_1 = Light_level_min ; // Distance correspondante
int Light_level_2 = Light_level_min ; // Distance correspondante
int Light_level_3 = Light_level_min ; // Distance correspondante
int Light_level_4 = Light_level_min ; // Distance correspondante
int Light_level_5 = Light_level_min ; // Distance correspondante
int Light_level_new = Light_level_min ; // Variable de stockage nouvelle valeur
int Light_level_new_1 = Light_level_min ; // Variable de stockage nouvelle valeur
int Light_level_new_2 = Light_level_min ; // Variable de stockage nouvelle valeur
int Light_level_new_3 = Light_level_min ; // Variable de stockage nouvelle valeur
int Light_level_new_4 = Light_level_min ; // Variable de stockage nouvelle valeur
int Light_level_new_5 = Light_level_min ; // Variable de stockage nouvelle valeur
int Light_level_old = Light_level_min ; // Variable de stockage ancienne valeur
int Light_level_i2c = Light_level_min ; // Variable intensité lumineuse envoyée - initialisé au seuil min

int VAR ; // Variable de stockage temporaire
const int T_auto = 16 ; // Durée pendant laquelle la valeur est disponible (en ms) - MODIF

int Time_1 ; // Durée du signal
int Time_2 ; // Durée du signal
int Time_3 ; // Durée du signal
int Time_4 ; // Durée du signal
int Time_5 ; // Durée du signal
const int Max_wait_time = 10000 ; // Correspond au Time d'attente maximum du retour ultrason (en us) - MODIF
int P_com = 0 ; // Variable passant a 1 si on interrompt la detection pour communication
const int Distance_min = 20 ; // Distance à partir de laquelle la lumière est au max (en cm) - MODIF
const int T_loop = 0 ; // Tempo avant nouvelle boucle acquisition (en ms)
//******************************************************************************************************************

// ************************************************ FONCTION SETUP *************************************************
void setup(){
Wire.begin(1); // Definition du numero esclave
Wire.onRequest(EVENT); // Definition du programme a lancer à la reception de la demande de com
pinMode(Pin_Trig_1,OUTPUT); // Declaration broche Trig
pinMode(Pin_Echo_1,INPUT); // Declaration broche Echo
pinMode(Pin_Trig_2,OUTPUT); // Declaration broche Trig
pinMode(Pin_Echo_2,INPUT); // Declaration broche Echo
pinMode(Pin_Trig_3,OUTPUT); // Declaration broche Trig
pinMode(Pin_Echo_3,INPUT); // Declaration broche Echo
pinMode(Pin_Trig_4,OUTPUT); // Declaration broche Trig
pinMode(Pin_Echo_4,INPUT); // Declaration broche Echo
pinMode(Pin_Trig_5,OUTPUT); // Declaration broche Trig
pinMode(Pin_Echo_5,INPUT); // Declaration broche Echo
}//*****************************************************************************************************************

// ************************************************* FONCTION LOOP *************************************************
void loop(){

// LUMIERE TOUJOURS ALLUME
if (MODE_LUM_ON == 1) {
Light_level_i2c = Light_level_max;
goto Endpoint;
}

// CAPTURE DISTANCE PAR CAPTEUR
if (CAPTEUR_1 == 1) {
digitalWrite(Pin_Trig_1, HIGH); // Allumage Ultrason
delayMicroseconds(10); // Tempo
P_com = 0; // reinitialisation variable de verif interruption com pendant detection
digitalWrite(Pin_Trig_1, LOW); // Extinction Ultrason
Time_1 = pulseIn(Pin_Echo_1, HIGH, Max_wait_time); // Récupère signal par broche LECTURE en us
if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection
if(Time_1 >= Max_wait_time){ // Condition si le Time est au max
Light_level_1 = Light_level_min;} // => alors ne pas allumer
else if (Time_1 <= 0) { // Condition si le Time est nul
Light_level_1 = Light_level_min;} // => alors ne pas allumer
else{ // Dans tous les autres cas
Light_level_1 = map(Time_1 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3
}
}

if (CAPTEUR_2 == 1) {
digitalWrite(Pin_Trig_2, HIGH); // Allumage Ultrason
delayMicroseconds(10); // Tempo
P_com = 0; // reinitialisation variable de verif interruption com pendant detection
digitalWrite(Pin_Trig_2, LOW); // Extinction Ultrason
Time_2 = pulseIn(Pin_Echo_2, HIGH, Max_wait_time); // Récupère signal par broche LECTURE en us
if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection
if(Time_2 >= Max_wait_time){ // Condition si le Time est au max
Light_level_2 = Light_level_min;} // => alors ne pas allumer
else if (Time_2 <= 0) { // Condition si le Time est nul
Light_level_2 = Light_level_min;} // => alors ne pas allumer
else{ // Dans tous les autres cas
Light_level_2 = map(Time_2 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3
}
}

if (CAPTEUR_3 == 1) {
digitalWrite(Pin_Trig_3, HIGH); // Allumage Ultrason
delayMicroseconds(10); // Tempo
P_com = 0; // reinitialisation variable de verif interruption com pendant detection
digitalWrite(Pin_Trig_3, LOW); // Extinction Ultrason
Time_3 = pulseIn(Pin_Echo_3, HIGH, Max_wait_time); // Récupère signal par broche LECTURE en us
if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection
if(Time_3 >= Max_wait_time){ // Condition si le Time est au max
Light_level_3 = Light_level_min;} // => alors ne pas allumer
else if (Time_3 <= 0) { // Condition si le Time est nul
Light_level_3 = Light_level_min;} // => alors ne pas allumer
else{ // Dans tous les autres cas
Light_level_3 = map(Time_3 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3
}
}

if (CAPTEUR_4 == 1) {
digitalWrite(Pin_Trig_4, HIGH); // Allumage Ultrason
delayMicroseconds(10); // Tempo
P_com = 0; // reinitialisation variable de verif interruption com pendant detection
digitalWrite(Pin_Trig_4, LOW); // Extinction Ultrason
Time_4 = pulseIn(Pin_Echo_4, HIGH, Max_wait_time); // Récupère signal par broche LECTURE en us
if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection
if(Time_4 >= Max_wait_time){ // Condition si le Time est au max
Light_level_4 = Light_level_min;} // => alors ne pas allumer
else if (Time_4 <= 0) { // Condition si le Time est nul
Light_level_4 = Light_level_min;} // => alors ne pas allumer
else{ // Dans tous les autres cas
Light_level_4 = map(Time_4 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3
}
}

if (CAPTEUR_5 == 1) {
digitalWrite(Pin_Trig_5, HIGH); // Allumage Ultrason
delayMicroseconds(10); // Tempo
P_com = 0; // reinitialisation variable de verif interruption com pendant detection
digitalWrite(Pin_Trig_5, LOW); // Extinction Ultrason
Time_5 = pulseIn(Pin_Echo_5, HIGH, Max_wait_time); // Récupère signal par broche LECTURE en us
if (P_com == 0) { // Prise en compte valeur si pas d'interruption pendant detection
if(Time_5 >= Max_wait_time){ // Condition si le Time est au max
Light_level_5 = Light_level_min;} // => alors ne pas allumer
else if (Time_5 <= 0) { // Condition si le Time est nul
Light_level_5 = Light_level_min;} // => alors ne pas allumer
else{ // Dans tous les autres cas
Light_level_5 = map(Time_5 / 68, Distance_min, (Max_wait_time / 68) , Light_level_max, Light_level_min);} // Regle de 3
}
}

// MOYENNE
if (MODE_MOYENNE == 1) {
Total_1 = Total_1 - Tableau_1[Index];
Tableau_1[Index] = Light_level_1;
Total_1 = Total_1 + Tableau_1[Index];
Moyenne_1 = Total_1 / Nb_val;
Light_level_new_1 = Moyenne_1;

Total_2 = Total_2 - Tableau_2[Index];
Tableau_2[Index] = Light_level_2;
Total_2 = Total_2 + Tableau_2[Index];
Moyenne_2 = Total_2 / Nb_val;
Light_level_new_2 = Moyenne_2;

Total_3 = Total_3 - Tableau_3[Index];
Tableau_3[Index] = Light_level_3;
Total_3 = Total_3 + Tableau_3[Index];
Moyenne_3 = Total_3 / Nb_val;
Light_level_new_3 = Moyenne_3;

Total_4 = Total_4 - Tableau_4[Index];
Tableau_4[Index] = Light_level_4;
Total_4 = Total_4 + Tableau_4[Index];
Moyenne_4 = Total_4 / Nb_val;
Light_level_new_4 = Moyenne_4;

Total_5 = Total_5 - Tableau_5[Index];
Tableau_5[Index] = Light_level_5;
Total_5 = Total_5 + Tableau_5[Index];
Moyenne_5 = Total_5 / Nb_val;
Light_level_new_5 = Moyenne_5;

Index = Index + 1;
if (Index >= Nb_val) {Index = 0;}
}
else if (MODE_MOYENNE == 0) {
Light_level_new_1 = Light_level_1; // Ecrasement de l'ancienne valeur à envoyer
Light_level_new_2 = Light_level_2; // Ecrasement de l'ancienne valeur à envoyer
Light_level_new_3 = Light_level_3; // Ecrasement de l'ancienne valeur à envoyer
Light_level_new_4 = Light_level_4; // Ecrasement de l'ancienne valeur à envoyer
Light_level_new_5 = Light_level_5; // Ecrasement de l'ancienne valeur à envoyer
}

// COMPARAISON DISTANCE
Light_level_new = min(128,Light_level_new_1);
Light_level_new = min(Light_level_new,Light_level_new_2);
Light_level_new = min(Light_level_new,Light_level_new_3);
Light_level_new = min(Light_level_new,Light_level_new_4);
Light_level_new = min(Light_level_new,Light_level_new_5);

// RAMPE
if (MODE_RAMPE == 1) {
if ((abs(Light_level_old - Light_level_new)) > Delta_adm) {
if (Light_level_old < Light_level_new) {
for (Light_level_i2c = Light_level_old ; Light_level_i2c <= Light_level_new; Light_level_i2c = Light_level_i2c + MOD) {
delay(T_auto/3);
}
}
else if (Light_level_old > Light_level_new) {
for (Light_level_i2c = Light_level_old ; Light_level_i2c >= Light_level_new ; Light_level_i2c = Light_level_i2c - MOD) {
delay(T_auto/3);
}
}
}
else {
Light_level_i2c = Light_level_new;
}
Light_level_old = Light_level_new;
}
else if (MODE_RAMPE == 0) {
Light_level_i2c = Light_level_new;
}

// ALEATOIRE
if (MODE_ALEATOIRE == 1) {
if (Light_level_i2c < Light_level_min) { // Cas valeur différente de 0
T_act = millis(); // Mémorisation temps actuel
if (Rand_Numb > 10000) {Rand_Numb = 0;} // Remet a zero la variable de stockage pour eviter debordement
Rand_Numb = Rand_Numb + 1; // Incrementation compteur
randomSeed(Rand_Numb); // Modifie le noyau de la fonction aleatoire
T_Light_auto_OFF_mem = random(T_Light_auto_OFF_min, T_Light_auto_OFF_max);} // Mémorisation valeur première attente
else { // Increment
if ((millis() - T_act) > T_Light_auto_OFF_mem) { // Temporisation inactif dépassé
Light_auto_mem = random(Light_auto_max, Light_auto_min); // Randomisation valeur intensité lumineuse
T_Light_auto_ON_mem = random(T_Light_auto_ON_min, T_Light_auto_ON_max); // Randomisation durée pendant laquelle la lumière est allumée
T_Light_auto_OFF_mem = random(T_Light_auto_OFF_min, T_Light_auto_OFF_max); // Randomisation durée d'attente jusqu'au prochain allumage
for (VAR = Light_level_min; VAR > Light_auto_mem; VAR = VAR--) { // Rampe montée lumière
Light_level_i2c = VAR; // Allumage
delay(T_auto); // Tempo
}
delay(T_Light_auto_ON_mem);
for (VAR = Light_auto_mem; VAR < Light_level_min; VAR = VAR++) { // Rampe descente lumière
Light_level_i2c = VAR; // Allumage
delay(T_auto); // Tempo
}
T_act = millis(); // Mémorisation temps actuel
}
}
}

// FIN
Endpoint:

delay(T_loop); // Ralenti la boucle d'acquisition

}//*********************************************************************************************************************

// ******************************************** FONCTION COMMUNICATION *************************************************
void EVENT(){
Wire.write(Light_level_i2c); // Commande exécutée lorsque le Master le demande
P_com = 1;
}//*********************************************************************************************************************

Done !
Actually it seems the LED is not responsible. I have to say I didn't want to unsolder so I tried other ways.
I took an other Uno and divided tasks. The first Uno, lets say "A", is connected in i2c slave and has to measure the distance and calculate the corresponding dimming level.
The second uno, then the "B" one, is the master reader. It asks every 40ms an update of the dimming level.

Then it works!

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.

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.

If some one is interested by the code, i can provide it !

Thank you diy_bloke for your help !
diy_bloke (author)  blacktrooper21 year ago
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.
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
diy_bloke (author)  blacktrooper21 year ago
Thanks. Obviously I am interested in your code.
I presume you use the PulseIn for the distance sensor, not for the Triac :-)
Hi,
Geat instructable !

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 ?
I'm desperately looking for it on the web but nothing !

Thanks in advance for your help


Chris
diy_bloke (author)  blacktrooper21 year ago
Well, the circuit in itself does not have that much to do with the interrupt use on an arduino.
Check this circuit: http://www.instructables.com/id/Arduino-controlled-light-dimmer-The-circuit/
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 !
I don't understand what do you mean by "polling the pin".
Sorry, I'm a beginner !

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 "breaks" the measurement which is time critical. I'm I clear ?
diy_bloke (author)  blacktrooper21 year ago
I think you are clear but it still should be possible to use more than one interrupt.
Do you mean that the interrupt function for the dimmer breaks the critical timing of yr HC SR04 timer?
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

'Polling' is to have your software check the status of a pin continuously.
Without knowing the exact software you are using for your sensor, it is hard to give more advice
diy_bloke (author)  diy_bloke1 year ago
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 :


//*************************************** DECLARATION VARIABLES ***************************************
int Signal_pin = 3; // Output to Opto Triac pin
int Sensor_output_pin = 8; // Broche Trig pour Ultrason
int Sensor_input_pin = 9; // Broche Echo pour Ultrason
int dimming_level = 128; // Dimming level (0-128) 0 = ON, 128 = OFF
//*****************************************************************************************************

//*****************************************************************************************************
void setup() {
Serial.begin(115200); // Open USB port
pinMode(Signal_pin, OUTPUT); // Set AC Load pin as output
pinMode(Sensor_output_pin, OUTPUT); // Set the trig pin for subsonic sensor
pinMode(Sensor_input_pin, INPUT); // Set the echo pin for subsonic sensor

attachInterrupt(0, zero_cross, RISING); // Choose the zero cross interrupt # from the table above
}//****************************************************************************************************

//*****************************************************************************************************
void zero_cross() {
// Function to be fired at the zero crossing to dim the light
// The interrupt function must take no parameters and return nothing
// Firing angle calculation : 1 full 50Hz wave =1/50=20ms
// Every zerocrossing thus:
// For 50Hz -> 20ms for 1 cycle
// -> 10ms for 1/2 cycle For 60Hz => 8.33ms
// 10ms = 10000us
// (10000us - 10us) / 128 = 75 (Approx) For 60Hz => 65
int dimming_time = (75*dimming_level); // For 60Hz =>65
delayMicroseconds(dimming_time); // Off cycle
digitalWrite(Signal_pin, HIGH); // Triac firing
delayMicroseconds(10); // Triac On propogation delay (for 60Hz use 8.33)
digitalWrite(Signal_pin, LOW); // Triac Off
}//****************************************************************************************************

//*****************************************************************************************************
void loop() {
digitalWrite(Sensor_output_pin,HIGH); // Subsonic signal send
delayMicroseconds(10); // Wait
digitalWrite(Sensor_output_pin,LOW); // Subsonic signal pin put to LOW
int Temps = pulseIn(Sensor_input_pin,HIGH,12000); // Wait and see if there is a signal
int dimming_level = map(Temps, 0, 12000, 30, 128); // Calculate the corresponding dimming level
Serial.println(dimming_level); // Send from USB port the value
}//****************************************************************************************************
diy_bloke (author)  blacktrooper21 year ago
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.

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.

Also, the PulseIn function is reported to have timing issues, some people have solved problems by lowering the baudrate.
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.

You let yr PulseIn wait for 12mS. Not sure if that is long enough for your sensor.
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.

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,

Sorry for the late reply.
I will try all your new ways in the week I hope and then I'll give you my feedback.

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.

I'm sooooo happy you try to help me !
Thank you very much
diy_bloke (author)  blacktrooper21 year ago
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:
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

or even :
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);

You are aware there is a library for the HC SR04 right?