Browse over 10,000 Electronics Projects

AC Power Control: Adjustable Phase Angle Control with triac using ATmega8

AC Power Control: Adjustable Phase Angle Control with triac using ATmega8

To clarify why power and voltage are not linearly related, let’s examine the formula relating the two.
So, assuming a constant resistance (be careful if you’re using incandescent lamps, since they are NOT constant resistance devices), power is directly proportional to the square of the voltage. So, if you half the voltage, the power is not halved, but is reduced to one-fourth the original power! One-fourth power with half the voltage!
Now let’s now go on to the design part – how we’re actually going to do this.
For the microcontroller, I’ve chosen the extremely popular ATmega8. However, since this application requires only a few pins, you can easily use any other small microcontroller for this purpose, such as ATtiny13.
The zero-crossing is done using the bridge-optocoupler method as I had previously shown.
Now, let’s take a look at the code:

//Programmer: Syed Tahmid Mahbub
//Compiler: mikroC PRO for AVR v2.10
//Target AVR: ATmega8
//Program for phase angle control – adjustable phase angle
unsigned char FlagReg;
unsigned char Count;
unsigned char i;
sbit ZC at FlagReg.B0;

void interrupt() org IVT_ADDR_INT0{
ZC = 1;

void main() {
DDRD = 0xFB;               //PORTD all output except PD2 – INT0
PORTD = 4;                 //Clear PORTD and enable pullup on PD2
DDRB = 0;                  //PORTB all input
PORTB = 0xFF;              //Enable pullups on PORTB
ISC01_bit = 1;             //External interrupt on falling edge
ISC00_bit = 0;
INT0_bit = 1;              //Enable ext int 0
INT1_bit = 0;              //Disable ext int 1
SREG_I_bit = 1;            //Enable interrupts


while (1){
if (ZC){ //zero crossing occurred
Count = (~PINB)+1;

for (i = 0; i < Count; i++){

PORTD.B0 = 1; //Send a pulse
PORTD.B0 = 0;

ZC = 0;

Take a look at the circuit diagram below. PORTB is connected to a DIP-switch.
Let me first talk about the DIP-switch. The DIP-switch I chose has 3 individual switches, each of which can take on or off position. So, the DIP-switch can have 8 possible states and we can assign a digital value to the DIP-switch states. Let’s assume that switch 0 is the switch connected to PORTB0/PINB0, that switch 1 is the switch connected to PORTB1/PINB1, and that switch 2 is the switch connected to PORTB2/PINB2. So, the possible DIP-switch states with their assigned values are:

0 – switch 0, switch 1 and switch 2 are all off
1 – switch 0 on, switch 1 and switch 2 are off
2 – switch 0 off, switch 1 on and switch 2 off
3 – switch 0 and switch 1 on and  switch 2 off
4 – switch 0 off, switch 1 off and switch 2 on
5 – switch 0 on, switch 1 off and switch 2 on
6 – switch 0 off, switch 1 and switch 2 on
7 – switch 0, switch 1 and switch 2 are all on

So, the DIP-switch can alter the values of PORTB0, PORTB1 and PORTB2. I made all of PORTB input pins and enabled the pull-ups. So, by default, all PORTB pins are high. When one of the switches is ON or shorted, that corresponding pin is low. So, only PORTB0, PORTB1 and PORTB2 can be switched to be high or low. The other pins will be high at all times. So, in order to read the value of the DIP-switch, I first inverted each individual bit of PORTB when reading (PINB) and then added 1 to the value as I wanted one to be the minimum value. Why one the minimum value? If you see the code later, you will see that the register “Count” is used to determine the delay time before the triac is fired. Count will have the value of the DIP-switch state plus one. I wanted a minimum delay before the triac is fired so that there is always a delay after the zero-crossing after the triac is fired. So, the function of the DIP-switch is now quite obvious. The DIP-switch sets the time after the zero-crossing after which the triac is fired. When only PORTB0/PINB0 is low, the delay time before firing the triac is minimum; it is equal to 800µs. When PORTB0/PINB0, PORTB1/PINB1 and PORTB2/PINB2 are all low, the delay time before firing the triac is maximum; it is equal to 800µs * 8 = 6.4ms. The adjusting delay time before firing adjusts the firing angle. How the time is related to the firing angle can be seen at the bottom of this article. The formula and an example are provided.

So, the program is basically as follows: