I am making a digital 12 dimmer light control system for Christmas lights. I am using a ATmega328 on a custom board with external 16MHz crystal at 5V. I'm in the US so mains is 120VAC RMS at 60Hz. I have an AC input, transistor output optocoupler connected to a hardware interrupt to detect zero cross. The antiparallel leds in the optocoupler are driven using a series capacitor and resistor straight from the mains. My outputs are Arduino pins 6-17. These drive DC input, triac output optocouplers which drive triacs.
My theory is to detect a zero cross and then turn on any pin not marked for off. I then scan an array which contains the percentages for each outlet. This number is mapped to 0 to 8333 representing the time, in microseconds, after the zero cross to turn the pin back off. This array then needs to be scanned at least 100 times between each zero cross for 1% resolution.
I set the outlets in 10% increments to showcase the dimming. Right now I get what appears to fully on down to 30%. 20% flickers and surges badly and 10% strobes/flickers but is consistently dim. This was tested on a 40w incandescent light bulb. I believe it to be a software issue and that is why I am here but I have included a basic hardware explanation in case.
I originally had the interrupt function call "on" (which calls dim) but this did not work as the code either still thought it was in an interrupt (crippling timing functions) and/or, because the interrupt pulled the program out of dim, dug a continuously deeper loop until freezing.
#include <IRremote.h>
#include <IRremoteInt.h>
int level[] = {
0, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10,100,100};//percentage on
// 1 2 3 4 5 6 7 8 9 10 11 12 :sockets-zero is placeholder
//int program = 0;
int x;
int limit = 11; //sets the number of sockets used. set to 12 to use all.
//unsigned long milli = 0;
unsigned long micro = 0;
volatile boolean interruptv = false;
void setup(){
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
pinMode(14, OUTPUT);
pinMode(15, OUTPUT);
pinMode(16, OUTPUT);
pinMode(17, OUTPUT);
pinMode(3, INPUT);
digitalWrite(3, HIGH);
attachInterrupt(1, interrupt, FALLING);
}
void loop(){
if (interruptv)
on();
}
void interrupt(){
interruptv = true;
}
void on(){
//delayMicroseconds(); //possibly accounts for time after trigger but
interruptv = false; //before zero cross (Vin is below voltage necessary to turn on ZC sensing leds.
for (x = 1; x <= limit; x++){
if (level[x] > 0)
digitalWrite((x+5), HIGH); //turns on all the plugs not set for off at the ZC
}
dim();
}
void dim(){
micro = micros(); //sets time of ZC
while(!interruptv){ //do until next ZC
for (x = 1; x <= limit; x++){//continuously look through the set levels to see if any need to be turned off. This should run at least 100 times every 8ms.
if( ((map(level[x], 0, 100, 0, 8333)) <= (micros() - micro)) && (level[x] < 100)){ //this should run every (limit * 100) every 8ms
digitalWrite((x+5), LOW);//turns lights off once their percentage of the 8ms cycle is complete.
}
}
}
}
I did some calculations and I think I had come up with 900 some clock cycles per percent of dimming. I would think this is enough but I could be wrong.
Any help would be appreciated.
Thanks,
GTech