Pages: [1]   Go Down
Author Topic: controlling two dimmers independently  (Read 20530 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*

 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
« Last Edit: December 07, 2013, 08:49:46 am by videorgb01 » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 300
Posts: 26217
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Three crost-posts deleted.

Do not cross-post.
Logged

"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.

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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/
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*
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
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*
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);

}


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 300
Posts: 26217
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: June 20, 2014, 03:50:06 am by AWOL » Logged

"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.

Pages: [1]   Go Up
Jump to: