Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[Moved] Ac voltage controller using pic microcontroller

Status
Not open for further replies.

faiz khan

Member level 1
Joined
Apr 30, 2015
Messages
35
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
263
Friends can any one help me how to control the firing angle by using a external push button to pic controller.....if anybody having code means please send.

THANK YOU
 

Hi,

This is often made.

Look for "phase control". Read about the technology. Study application notes. Look for hardware and software.
Then try to build it for your own by using and modifying the given informations.

If you encounter any problems, then show us what you did, what you expect and give a detailed error description.

Klaus
 
The code which i used is below.my objective is to program pic controller such that if we press push buttons the firing angle OF TRIAC should increase or decrease .please help me by correcting the code.
THANK YOU


Code:
unsigned char FlagReg;
sbit ZC at FlagReg.B0;
int x;
void interrupt()
{
     int i;
     if (INTCON.INTF)
     {          //INTF flag raised, so external interrupt occured
      //  ZC = 1;
        INTCON.INTF = 0;
   //  }
     //if (ZC){ //zero crossing occurred

              for(i=1;i<=x;i++)
              {
              delay_ms(1);
              }
              PORTD.B0 = 1; //Send a pulse
              delay_us(250);
              PORTD.B0 = 0;
              //ZC = 0;
             // }
        }
}

void main() {
      x=1;
     PORTB = 0;
     TRISB = 0x01;              //RB0 input for interrupt
     PORTA = 0;
     ADCON1 = 7;                 //Disable ADC
     TRISA = 0xFF;                                //Make all PORTA inputs
     PORTD = 0;
     TRISD = 0;                 //PORTD all output
     OPTION_REG.INTEDG = 0;      //interrupt on falling edge
     INTCON.INTF = 0;           //clear interrupt flag
     INTCON.INTE = 1;           //enable external interrupt
     INTCON.GIE = 1;            //enable global interrupt


     while (1)
     {
     if((RC5==0))
     {
     x=x+1;
     //delay_ms(1);
     }
     if((RC6==0))
     {
      x=x-1;
     //delay_ms(1);
     }
     }
}
 
Last edited by a moderator:

Hi,

You tell nothing about your hardware so it is hard for us to guess what you want to do.
Please give more detailed informtion and more users will answer

****

You know ho it should work? Do you have a zero cross hardware? How does it work?

***

A busy wait within an interrupt is no good idea.
It´s better to start a timer/counter, maybe in waveform generation mode, to generate the firing pulse without software.

***

Post schematic, and additional informations like controller type, frequency, pahse adjust range and -resolution and so on.

Klaus
 
I am doing a project on TRIAC based voltage controller with resistive load.
the components i am using are BT137(TRIAC),MOC3041(OPTOISOLATOR-WITH ZCD).

by using PIC16F877A i want to control the firing angle of TRIAC for which i am using 2 push buttons,one for incrementing and one for decrementing firing angle....

please help me code friends...


THANK YOU
 

I can help you with the code for your project but I have to know which compiler you are using. From the code that you have posted it seems you are using mikroC PRO PIC Compiler. Is it right ?

Have a look at this thread.

https://www.edaboard.com/threads/332532/
 

yes am using mikroc PRO PIC compiler and PIC16F877A
can you please help me by providing code
THANK YOU
 

Did you see the link I posted in post #7. How many steps do you need. Is 10 steps of power control enough ? Are you simulating in Proteus or testing in hardware. Please provide the circuit.

Should the least power turn of the device or do you want another button to turn ON/OFF the device ?

What is your AC frequency ? 50 Hz or 60 Hz ?
 

1. get rid of the delay in the interrupt.
2. note that your steps are set to 1mS minimum, that gives you no more than 20 levels at 50Hz and 16 levels at 60Hz.
3. limit your number of steps, you can currently go from -32767 (!) to +32768 when it should be 0 to +20 or 0 to +16

You would do better to configure a hardware timer to count to maximum in one half AC cycle, pre-set it with your 'x' value and fire the triac as the timer overflows. It gives greater control accuracy, more steps although you can decide their size in software and also leaves the PIC able to do some other task at the same time.

The frequency can easily be measured by counting between zero crossings so it isn't really necessary to know it beforehand.

Brian.
 
Did you see the link I posted in post #7. How many steps do you need. Is 10 steps of power control enough ? Are you simulating in Proteus or testing in hardware. Please provide the circuit.

Should the least power turn of the device or do you want another button to turn ON/OFF the device ?

What is your AC frequency ? 50 Hz or 60 Hz ?

YES i saw that post ....my circuit is also same as that circuit.first i am simulating in Proteus and then has to implement hardware.

my circuit is same what is there in the link in post#7 but with pic16f877a.

i want to use 2 push buttons for incrementing and decrementing firing angle ...9 steps are enough for both push buttons

THANK YOU
 
Last edited by a moderator:

I made the code but Proteus is not showing the TRIAC signal. Maybe betwixt can help.

@betwixt

Please check the code I have attached. If you have Proteus then please check why TRIAC signal is not showing.
 

Attachments

  • PIC16F877A Based Dimmer.rar
    39.2 KB · Views: 148

it is not opening friend...please send in pdf format
 

Here is the circuit. TRIAC is firing but TRIAC signal is not present. maybe it is a Proteus problem. Test it in hardware.
 

Attachments

  • dimmer.png
    dimmer.png
    79.1 KB · Views: 160

thank you can you send the code please.....
 

Here is the code. Compiled for 4 MHz XT Oscillator.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
unsigned char milliSec = 0, count = 0;
 
//Timer0
//Actual Interrupt Time : 1 ms
//Place/Copy this part in declaration section
void InitTimer0() {
    OPTION_REG = 0x81;
    TMR0 = 6;
    TMR0IE_bit = 1;
}
 
void interrupt() {
     if(INTF_bit) {
        INTF_bit = 0;
        INTE_bit = 0;
        InitTimer0();
        INTEDG_bit = ~INTEDG_bit;
     }
     
     if(TMR0IF_bit) {
        TMR0IF_bit = 0;
        TMR0 = 6;
        //Enter your code here
        if(++count == (milliSec + 1)) {
            TMR0IE_bit = 0;
            PORTD.F0 = 1;
            //Delay_us(200);
            PORTD.F0 = 0;
            count = 0;
            INTE_bit = 1;
        }
     }
}
 
void main() {
 
     CMCON = 0x07;
     ADCON1 = 0x87;
     
     TRISA = 0xC0;
     TRISB = 0x07;
     TRISC = 0x00;
     TRISD = 0x00;
     TRISE = 0x00;
 
     PORTA = 0x00;
     PORTB = 0x07;
     PORTC = 0x00;
     PORTD = 0x00;
     PORTE = 0x00;
 
     INTEDG_bit = 0;
     INTF_bit = 0;
     INTE_bit = 1;
 
     GIE_bit = 1;
     
     while (1){
 
            if(RB1_bit) {
                 Delay_ms(50);
                 while(RB1_bit);
                      if(milliSec < 8)++milliSec;
            }
            
            if(RB2_bit) {
                 Delay_ms(50);
                 while(RB2_bit);
                      if(milliSec > 0)--milliSec;
            }
     }
}

 

Replace 4N37 with MOC3021 in the TRIAC firing circuit.

Try this code in Proteus.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
unsigned char milliSec = 0, count = 0;
 
//Timer0
//Actual Interrupt Time : 1 ms
//Place/Copy this part in declaration section
void InitTimer0() {
    OPTION_REG = 0x81;
    TMR0 = 6;
    TMR0IE_bit = 1;
}
 
void interrupt() {
     if(INTF_bit) {
        INTF_bit = 0;
        INTE_bit = 0;
        InitTimer0();
        INTEDG_bit = ~INTEDG_bit;
     }
     
     if(TMR0IF_bit) {
        TMR0IF_bit = 0;
        TMR0 = 6;
        //Enter your code here
        if(++count == (milliSec + 1)) {
            TMR0IE_bit = 0;
            PORTD.F0 = 1;
            Delay_us(200);
            PORTD.F0 = 0;
            count = 0;
            INTE_bit = 1;
        }
     }
}
 
void main() {
 
     CMCON = 0x07;
     ADCON1 = 0x87;
     
     TRISA = 0xC0;
     TRISB = 0x07;
     TRISC = 0x00;
     TRISD = 0x00;
     TRISE = 0x00;
 
     PORTA = 0x00;
     PORTB = 0x00;
     PORTC = 0x00;
     PORTD = 0x00;
     PORTE = 0x00;
 
     INTEDG_bit = 0;
     INTF_bit = 0;
     INTE_bit = 1;
 
     PEIE_bit = 1;
     GIE_bit = 1;
     
     while (1){
 
            if(RB1_bit) {
                 Delay_ms(50);
                 while(RB1_bit);
                      if(milliSec < 9)++milliSec;
            }
            
            if(RB2_bit) {
                 Delay_ms(50);
                 while(RB2_bit);
                      if(milliSec > 0)--milliSec;
            }
     }
}



- - - Updated - - -

Working project attached. See image for circuit. This is the code. Compile it for 4 MHz XT Oscillator. Test in Proteus and also hardware and reply.

The problem with the previous codes were because of using Timer0. I changed it to Timer1 and everything started working as needed.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
unsigned char milliSec = 0, count = 0;
 
//Timer1
//Prescaler 1:1; TMR1 Preload = 64536; Actual Interrupt Time : 1 ms
//Place/Copy this part in declaration section
void InitTimer1(){
    T1CON = 0x01;
    TMR1IF_bit = 0;
    TMR1H = 0xFC;
    TMR1L = 0x18;
    TMR1IE_bit = 1;
}
 
void interrupt() {
     if(INTF_bit) {
        INTF_bit = 0;
        INTEDG_bit = ~INTEDG_bit;
        //INTE_bit = 0;
        InitTimer1();
 
     }
     
     if(TMR1IF_bit) {
        TMR1IF_bit = 0;
        TMR1H = 0xFC;
        TMR1L = 0x18;
        //Enter your code here
        if(++count == (milliSec + 1)) {
            TMR1ON_bit = 0;
            PORTD.F0 = 1;
            Delay_us(200);
            PORTD.F0 = 0;
            count = 0;
            //INTE_bit = 1;
        }
     }
}
 
void main() {
 
     CMCON = 0x07;
     ADCON1 = 0x87;
     
     TRISA = 0xC0;
     TRISB = 0x07;
     TRISC = 0x00;
     TRISD = 0x00;
     TRISE = 0x00;
 
     PORTA = 0x00;
     PORTB = 0x00;
     PORTC = 0x00;
     PORTD = 0x00;
     PORTE = 0x00;
 
     INTEDG_bit = 0;
     INTF_bit = 0;
     INTE_bit = 1;
 
     PEIE_bit = 1;
     GIE_bit = 1;
     
     while (1){
 
            if(RB1_bit) {
                 Delay_ms(50);
                 while(RB1_bit);
                      if(milliSec < 9)++milliSec;
            }
            
            if(RB2_bit) {
                 Delay_ms(50);
                 while(RB2_bit);
                      if(milliSec > 0)--milliSec;
            }
     }
}




Try this code. Changed the Timer delay value. Earlier it was 1 ms and now it is 875 us.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
unsigned char milliSec = 0, count = 0;
 
//Timer1
//Prescaler 1:1; TMR1 Preload = 64711; Actual Interrupt Time : 825 us
//Place/Copy this part in declaration section
void InitTimer1(){
    T1CON = 0x01;
    TMR1IF_bit = 0;
    TMR1H = 0xFC;
    TMR1L = 0x95;
    TMR1IE_bit = 1;
}
 
void interrupt() {
     if(INTF_bit) {
        INTF_bit = 0;
        INTEDG_bit = ~INTEDG_bit;
        //INTE_bit = 0;
        InitTimer1();
 
     }
     
     if(TMR1IF_bit) {
        TMR1IF_bit = 0;
        TMR1H = 0xFC;
        TMR1L = 0x95;
        //Enter your code here
        if(++count == (milliSec + 1)) {
            TMR1ON_bit = 0;
            PORTD.F0 = 1;
            Delay_us(100);
            PORTD.F0 = 0;
            count = 0;
            //INTE_bit = 1;
        }
     }
}
 
void main() {
 
     CMCON = 0x07;
     ADCON1 = 0x87;
     
     TRISA = 0xC0;
     TRISB = 0x07;
     TRISC = 0x00;
     TRISD = 0x00;
     TRISE = 0x00;
 
     PORTA = 0x00;
     PORTB = 0x00;
     PORTC = 0x00;
     PORTD = 0x00;
     PORTE = 0x00;
 
     INTEDG_bit = 0;
     INTF_bit = 0;
     INTE_bit = 1;
 
     PEIE_bit = 1;
     GIE_bit = 1;
     
     while (1){
 
            if(RB1_bit) {
                 Delay_ms(50);
                 while(RB1_bit);
                      if(milliSec < 9)++milliSec;
            }
            
            if(RB2_bit) {
                 Delay_ms(50);
                 while(RB2_bit);
                      if(milliSec > 0)--milliSec;
            }
     }
}

 

Attachments

  • PIC16F877A Based Dimmer Working.rar
    138 KB · Views: 141
  • dimmer working.png
    dimmer working.png
    110.5 KB · Views: 151
Last edited:
@betwixt

Please check the code I have attached. If you have Proteus then please check why TRIAC signal is not showing.

I don't use Proteus or MikroC but I keep a copy of Mikro programs (trial versions) for helping people on here. For 'production' use I wouldn't touch it!

Suggestion: move the resistor in series with the ZCD opto-coupler so it is in series with the AC to the bridge rather than the opto itself. You can then use smaller diodes and if necessary add a small capacitor across the bridge AC points to reduce interference pick up. Obviously, use an opto-triac instead of U2 and I suggest using the circuit in the triac data sheet rather than just feeding the gate current through a 1K resistor.

Brian.
 
OK betwixt.

Can I use this circuit for ZCD ? Is it safe ? I have used 5.1V zener diodes. If mains voltage increases above 240 or 260V then Zener has to bypass it.

See the attached video. It shows the Proteus simulation.
 

Attachments

  • ZCD.png
    ZCD.png
    97 KB · Views: 145
  • Phase Angle Control Proteus Simulation.rar
    295.3 KB · Views: 136
Last edited:
If you use that for ZCD, why not use ordinary Schottky signal diodes? Wired between ground and VDD they will clamp the incoming AC to within VSS-0.25V and VDD+0.25V which is better than the Zeners will achieve. For safety sake, I would add a resistor of say 10K in series with the PIC input and make the resistor in series with the AC something like 150K or more. The current into the PIC is almost zero so you can safely use quite high value resistors.

AC ---> 150K ---> diodes to VSS & VDD ---> 10K ---> PIC pin.

Suggest diode type BAT85 or equivalent. Be careful with supply to the PIC, your schematics show it connected to one side of the AC so make sure you can't touch anything, especially the switch wiring!

Brian.
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top