Go Down

Topic: controlling two dimmers independently (Read 22230 times) previous topic - next topic

Dec 07, 2013, 02:41 pm Last Edit: Dec 07, 2013, 02:49 pm by videorgb01 Reason: 1
Hi,

I am trying to control two dimmers independently with an arduino duemilanove. The dimmer is produced by inmojo (http://www.inmojo.com/store/inmojo-market/item/digital-ac-dimmer-module-lite-v.2/). I tried to use two functions to detect the pass by zero, but one of the functions interrupted the other one. I tried to set a variable to indicate when one of them is done, with no luck. Here is the code

Code: [Select]

/*

AC Light Dimmer - Inmojo
AC Voltage dimmer with Zero cross detection

Author: Charith Fernanado http://www.inmojo.com charith@inmojo.com
License: Released under the Creative Commons Attribution Share-Alike 3.0 License.
http://creativecommons.org/licenses/by-sa/3.0
Target:  Arduino

Attach the Zero cross pin of the module to Arduino External Interrupt pin
Select the correct Interrupt # from the below table

Pin    |  Interrrupt # | Arduino Platform
---------------------------------------
2      |  0            |  All
3      |  1            |  All
18     |  5            |  Arduino Mega Only
19     |  4            |  Arduino Mega Only
20     |  3            |  Arduino Mega Only
21     |  2            |  Arduino Mega Only

*/

int AC_LOAD_0 = 4;    // Output to Opto Triac pin
int AC_LOAD_1 = 5;    // Output to Opto Triac pin
int dir_0 = 0; //defines the dimming direction
int dimtime_0;
int dimtime_1;
int minV = 104; //min dimmer value
int maxV = 24;  //max dimmer value
int dimming_0 = (minV+maxV)/2;  // Dimming level (0-128)  0 = ON, 128 = OFF
int dimming_1 = (minV+maxV)/2;  // Dimming level (0-128)  0 = ON, 128 = OFF
int zeroW = 0;

void setup()
{
 Serial.begin(9600);
 delay(1000);
 pinMode(AC_LOAD_0, OUTPUT);      // Set the AC Load as output
 pinMode(AC_LOAD_1, OUTPUT);      // Set the AC Load as output
 attachInterrupt(0, zero_crosss_int_0, RISING);  // Choose the zero cross interrupt # from the table above
 attachInterrupt(1, zero_crosss_int_1, RISING);  // Choose the zero cross interrupt # from the table above
}

void loop()
{
 Serial.println(dimming_0);
 //dimmer 0
 if(dimming_0>minV) dir_0=1;
 if(dimming_0<maxV) dir_0=0;
 if(dir_0==1) dimming_0--;
 if(dir_0==0) dimming_0++;
 //dimmer 1
 dimming_1=(dimming_0*(-1))+minV+maxV;
 Serial.println(dimming_1);
 delay(100);
}

void zero_crosss_int_0()  // function to be fired at the zero crossing to dim the light
{
//  if(zeroW == 0){
 // Firing angle calculation :: 60Hz-> 8.33ms (1/2 Cycle)
 // (8333us - 8.33us) / 128 = 65 (Approx)  
   int dimtime_0 = (65*dimming_0);      
   delayMicroseconds(dimtime_0);    // Off cycle
   digitalWrite(AC_LOAD_0, HIGH);   // triac firing
   delayMicroseconds(8.33);         // triac On propogation delay
   digitalWrite(AC_LOAD_0, LOW);    // triac Off
//   zeroW = 1;
//  }
}

void zero_crosss_int_1()  // function to be fired at the zero crossing to dim the light
{
 // Firing angle calculation :: 60Hz-> 8.33ms (1/2 Cycle)
 // (8333us - 8.33us) / 128 = 65 (Approx)  
//  if(zeroW == 1){
   int dimtime_1 = (65*dimming_1);      
   delayMicroseconds(dimtime_1);    // Off cycle
   digitalWrite(AC_LOAD_1, HIGH);   // triac firing
   delayMicroseconds(8.33);         // triac On propogation delay
   digitalWrite(AC_LOAD_1, LOW);    // triac Off
//    zeroW = 0;
//  }
}


Thanks for your attention.
Best

AWOL

Three crost-posts deleted.

Do not cross-post.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

You should have only one interrupt to detect zero cross, as is the same timing for both loads.
Besides that, you should not use delay() or delaymicroseconds() inside an interrupt call.

Take a look at this http://playground.arduino.cc/Code/ACPhaseControl, it will give you some ideas

and here's another example of an arduino-controlled dimmer (look for the download link at the bottom of the page):  http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/

Ok, I'm back after some research. I'm actually working on the same thing; that is controlling two dimmers from one arduino.
Putting the hardware together, I've tried the circuit shown here:
http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/
and it works like a charm.
I've modified the code to work with two dimmers instead. I didn't try it yet but it should work.
I'll put this together this weekend and try the code so I'll post the circuit and the code if it needs tweaking.
As you see, there's no delay() or delayMicroseconds() ... I've read somewhere that those don't work inside an interrupt function.
Here's the code:
Code: [Select]

/*
AC dual dimmer Control
adapted from sketch by Robert Twomey <rtwomey@u.washington.edu>
http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/
*/

#include <TimerOne.h>           // Avaiable from http://www.arduino.cc/playground/Code/Timer1

volatile int i=0;               // Variable to use as a counter
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin1 = 11;                // Output to Opto Triac load#1
int AC_pin2 = 12; // Output to Triac load #2
int dim1 = 0;
int dim2 = 0;                    // Dimming level (0-128)  0 = on, 128 = 0ff


int freqStep = 65;    // This is the delay-per-brightness step in microseconds.
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want.
//
// 1000000 us / 120 Hz = 8333 uS, length of one half-wave.
// 8333 uS / 128 steps = 65 uS / step
//

void setup() {                                      // Begin setup
  pinMode(AC_pin, OUTPUT);                          // Set the Triac pin as output
  attachInterrupt(0, zero_cross_detect, RISING);   // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);     
  // Use the TimerOne Library to attach an interrupt
  // to the function we use to check to see if it is
  // the right time to fire the triac.  This function
  // will now run every freqStep (65 uS for a 60Hz sinewave).                                           
}

void zero_cross_detect() {   
  i=0;
  // since the control pin stays high, the TRIAC won't 'unlatch'
  // when zero-crossing, so I need to put the pins to LOW
  digitalWrite(AC_pin1, LOW);
  digitalWrite(AC_pin2, LOW);
  // writing pins is like 10 times faster if
  // we write the register directly
  // instead of using 'digitalWrite'
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
    if(i>=dim1) {                     
      digitalWrite(AC_pin1, HIGH); // turn on triac #1
    }
if (i>=dim2) {
digitalWrite(AC_pin2, HIGH); // turn on triac #2
    }                               
    i++; // increment time step counter
}                                   

void loop() {                       
  // here goes the code that sets the global variables dim1 and dim2 to the values you want
}


Hi,

Thanks for your help. I ended up using two arduinos. One sends the commands to the other, so both crossing zero processes are independently.

Best

I used a code that has a delaymicrosecond to control the triac. It worked fine. It is here

http://www.inmojo.com/store/inmojo-market/item/digital-ac-dimmer-module-lite-v.2/

If you manage to do it just with one, I would like to know how you solved. I spend some time trying, but my coding skills are not good. I had problems synchronising the triacs.

Best

I don't know why your code works, because (again) delaymicroseconds() doesn't work inside an interrupt call, that's arduino, and we can't do anything about it.

I finally managed to make a double dimmer and it is working beautifully. Check this schematics, I used exactly the same circuit:

http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/images/1814d.png

but I repeated the dimmer part twice. The code I used is based on the sketch I found in that page, but I heavily modified to make it cleaner and simpler... and of course, to work with two signals from the arduino.

the sketch I wrote, dims one light while raising the other, and vice-versa. You can change the loop in the sketch to do wathever you want with the dimmers, all you have to do is to set the dim1 and dim2 variables. Here it is, I hope you will find it useful.

Code: [Select]

/*
AC dual dimmer Control
adapted from sketch by Robert Twomey <rtwomey@u.washington.edu>
http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/
*/

#include <TimerOne.h>           // Avaiable from http://www.arduino.cc/playground/Code/Timer1

volatile int i=0;               // Variable to use as a counter
int AC_pin1 = 4;                // Output to Opto Triac load#1
int AC_pin2 = 5; // Output to Triac load #2
int dim1 = 0;
int dim2 = 0;                    // Dimming level (0-128)  0 = on, 128 = 0ff
int inc=1;

int freqStep = 65;    // This is the delay-per-brightness step in microseconds.
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want.
//
// 1000000 us / 120 Hz = 8333 uS, length of one half-wave.
// 8333 uS / 128 steps = 65 uS / step
//

void setup() {   
  // Begin setup
  //Serial.begin(9600);
  pinMode(AC_pin1, OUTPUT);                          // Set the Triac pin as output
  pinMode(AC_pin2, OUTPUT);
  attachInterrupt(0, zero_cross_detect, RISING);   // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);     
  // Use the TimerOne Library to attach an interrupt
  // to the function we use to check to see if it is
  // the right time to fire the triac.  This function
  // will now run every freqStep (65 uS for a 60Hz sinewave).                                           
}

void zero_cross_detect() {   
  i=0;
  // since the control pin stays high, the TRIAC won't 'unlatch'
  // when zero-crossing, so I need to put the pins to LOW
  digitalWrite(AC_pin1, LOW);
  digitalWrite(AC_pin2, LOW);
  // writing pins is like 10 times faster if
  // we write the register directly
  // instead of using 'digitalWrite'
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
    if(i>=dim1) {                     
      digitalWrite(AC_pin1, HIGH); // turn on triac #1
    }
    if (i>=dim2) {
      digitalWrite(AC_pin2, HIGH); // turn on triac #2
    }                               
    i++; // increment time step counter
}                                   

void loop() {                       
    dim1+=inc;
    if (dim1>=127 | dim1<=0){
      inc*=-1;
    }

    dim2=127-dim1;
    digitalWrite(13,HIGH);
    delay(30);
    digitalWrite(13,LOW);
    delay(30);

}




Ed1960

I have been using 'delayMicroseconds' in an interrupt  and it works like a charm. In fact I never see any warning (other than here)  that it couldnt be used.
Sure if your delay is still busy when a new interrupt comes, it will screw up timing, but  with the dimmer you have 10 (or 8,3) miliseconds before  a new interrupt comes so say a delay of 10uS shouldnt be a problem
Yes, in the past there was a problem, but as of Arduino 0018, delayMicroseconds() no longer disables interrupts.

AWOL

#8
Jun 20, 2014, 10:47 am Last Edit: Jun 20, 2014, 10:50 am by AWOL Reason: 1
Quote
I don't know why your code works, because (again) delaymicroseconds() doesn't work inside an interrupt call, that's arduino, and we can't do anything about it.

Complete rubbish.
You shouldn't use it, but that's not the same as saying you can't

This has already been pointed out to you here
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Go Up