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.

Why this is not working ?

Status
Not open for further replies.

milan.rajik

Banned
Advanced Member level 5
Joined
Apr 1, 2013
Messages
2,524
Helped
540
Reputation
1,078
Reaction score
524
Trophy points
1,393
Activity points
0
Why this is not working ?

The project is AC Light dimmer or Fan speed control. I am using PIC18F45K22 @ 4 MHz external Clock. I am using mikroC PRO PIC Compiler. Proteus 8.1 SP1 file is attached.

My calculations are like this

AC freq = 50 Hz

Period (T) = 1 / 50 = 0.02 sec

T / 2 = 0.01 sec = 10 ms

Minimum time after Zero Cross and before firing TRIAC is 2 ms.

Time span is 10ms - 2ms = 8 ms

I need 8 steps of increment and 8 steps of decrement.

1 ms is increased or decreased every step.

VDelay() function is used.

RB1 and RB2 buttons are using to decrement and increment the fan speed.

I have tested in Proteus and it is not working. I have not yet tested it in hardware. I have ordered the required parts for testing in hardware.
 

Attachments

  • AC Light Dimmer or Fan Speed Control.rar
    54.5 KB · Views: 260
  • dimmer.png
    dimmer.png
    153.8 KB · Views: 355

I cannot reconcile your comment that you are using a 4MHZ external clock with the CLKI pin on the MCU not being connected to anything.
You may want to expand a bit more on "...it is not working".
Does it compile (I assume so as you seem to have included some files that are derived from the source file)?
What does it do that you do not expect it to?
What does it not do that you expect it to?
Is there a bug in Proteus that is masking the real situation?
Susan
 
Yes, the code compiles fine. When RB1 button is pressed and released then

Code C - [expand]
1
VDelay(2 + x, 4000)

function will create a delay in milli sec like

if x is 1 ms (when button pressed and released once) then VDelay(3, 4000) will cause a 3 ms delay and after that TRIAC is fired and TRIAC has to conduct till next ZC (Zero cross) and again after next ZC it has to fire the TRIAC after 3 ms and this has to continue.

So, for button press and release these will be the delays

RB1 button

press and release (p/r) 1 3 ms then TRIAC fire
p/r 2 4 ms then TRIAC fire
p/r 3 5 ms then TRIAC fire
p/r 4 6 ms then TRIAC fire
p/r 5 7 ms then TRIAC fire
p/r 6 8 ms then TRIAC fire
p/r 7 9 ms then TRIAC fire
p/r 8 10 ms then TRIAC fire


For button RB2 this goes in reverse.

So, When x goes from 0 to 8 then conduction angle goes decreasing and light has to dim. When x goes from max to 0 then delay decreased and conduction angle increases and light brightness has to increase.

- - - Updated - - -

Edit:

See this image. This is what I want. The conduction angle has to be controlled in both positive and negative half cycles of the AC.

while(!ZC) will wait till ZC accours and then minimum delay will be VDelay, Advances_ms(2 + 0, 4000) = 2 ms delay and after this TRIAC fires and conducts till end of the half cycle. If you see my oscilloscope data it shows after positive going ZC there is no chopping of AC but the chopping occurs 2 ms before the end of half cycle but the negative half cycle is chopped properly that is after positive to negative going ZC there is 2 ms delay and after that TRIAC is fired.



RB1 button goes on decreasing the conduction angle by increasing the delay before which the TRIAC fires and RB2 button increases the conduction angle by decreasing the delay after which TRIAC fires.

See fig 3 tp 7 here.

https://tahmidmc.blogspot.in/2013/06/power-control-with-thyristor-phase.html

The conduction angles has to decrease lie this on successive RB1 button press and release.

- - - Updated - - -

I changed the code a little. I removed the fixed 2 msec delay.


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
unsigned char myFlags;
unsigned char milliSec = 0;
 
sbit ZC at myFlags.B0;
 
void interrupt() {
     if (INT0IF_bit){
        ZC = 1;
        INT0IF_bit = 0;
     }
}
 
void main() {
 
     ANSELA = 0x00;
     ANSELB = 0x00;
     ANSELC = 0x00;
     ANSELD = 0x00;
     ANSELE = 0x00;
     
     TRISA = 0xFF;
     TRISB = 0x07;
     TRISD = 0x00;
     
     PORTA = 0x00;
     PORTB = 0x00;
     PORTD = 0x00;
     
     LATA = 0x00;
     LATB = 0x00;
     LATD = 0x00;
 
     INTEDG0_bit = 0;
     INT0IF_bit = 0;
     INT0IE_bit = 1;
     PEIE_bit = 1;
     GIE_bit = 1;
     
     while (1){
 
            if(RB1_bit) {
                 Delay_ms(100);
                 if(RB1_Bit)
                    if(milliSec < 10)milliSec += 1;
                    
                    Delay_ms(1000);
            }
            
            if(RB2_bit) {
                 Delay_ms(100);
                 if(RB2_Bit)
                    if(milliSec > 0)milliSec -= 1;
                 Delay_ms(1000);
            }
 
            while(!ZC);
            VDelay_Advanced_ms(milliSec, 4000);  //Fire TRIAC after 1, 2, 3, 4, 5, 6, 7, 8, 9, msec for RB1 button press and release
                                                 //Fire TRIAC after 9, 8, 7, 6, 5, 4, 3, 2, 1 msec for RB2 button press and release
            PORTD.F0 = 1;
            Delay_us(250);
            PORTD.F0 = 0;
            ZC = 0;
     }
}



- - - Updated - - -


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
78
79
80
81
82
83
84
85
86
87
88
unsigned char myFlags;
unsigned char milliSec = 0, counter = 0;
 
sbit ZC at myFlags.B0;
 
//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 500 ms
 
//Place/Copy this part in declaration section
void InitTimer1() {
  T1CON = 0x31;
  TMR1IF_bit = 0;
  TMR1H = 0x0B;
  TMR1L = 0xDC;
  TMR1IE_bit = 1;
  INTCON = 0xC0;
}
 
void interrupt() {
     if (INT0IF_bit){
        ZC = 1;
        INT0IF_bit = 0;
     }
     
     if(TMR1IF_bit) {
          if(++counter == 2) {                 
                 counter = 0;
                 TMR1ON_bit = 0;
          }
          TMR1IF_bit = 0;
          TMR1H = 0x0B;
          TMR1L = 0xDC;
     }
}
 
void main() {
 
     ANSELA = 0x00;
     ANSELB = 0x00;
     ANSELC = 0x00;
     ANSELD = 0x00;
     ANSELE = 0x00;
     
     TRISA = 0xFF;
     TRISB = 0x07;
     TRISD = 0x00;
     
     PORTA = 0x00;
     PORTB = 0x00;
     PORTD = 0x00;
     
     LATA = 0x00;
     LATB = 0x00;
     LATD = 0x00;
 
     INTEDG0_bit = 0;
     INT0IF_bit = 0;
     INT0IE_bit = 1;
     PEIE_bit = 1;
     GIE_bit = 1;
     
     while (1){
 
            if((RB1_bit) && (!TMR1ON_bit)) {
                 Delay_ms(100);
                 if((RB1_bit) && (!TMR1ON_bit))
                    if(milliSec < 10)milliSec += 1;
                    
                    InitTimer1();
            }
            
            if((RB2_bit) && (!TMR1ON_bit)) {
                 Delay_ms(100);
                 if((RB2_bit) && (!TMR1ON_bit))
                    if(milliSec > 0)milliSec -= 1;
                    
                 InitTimer1();
            }
 
            while(!ZC);
            VDelay_Advanced_ms(milliSec, 4000);  //Fire TRIAC after 1, 2, 3, 4, 5, 6, 7, 8, 9, msec for RB1 button press and release
                                                 //Fire TRIAC after 9, 8, 7, 6, 5, 4, 3, 2, 1 msec for RB2 button press and release
            PORTD.F0 = 1;
            Delay_us(250);
            PORTD.F0 = 0;
            ZC = 0;
     }
}

 

Attachments

  • Regulated_rectifier wiki.gif
    Regulated_rectifier wiki.gif
    93 KB · Views: 254
  • VDelay.png
    VDelay.png
    108.5 KB · Views: 242
Last edited:

Buried in all of that is what I think you are describing as your problem: the switching is only occurring at the start of the negative-going half cycle of the incoming AC signal.
It is really hard to see your circuit with the large image of the scope sitting over much of it, but it would seem that you have some sort of signal going in to the INT0 pin and you are using that to detect the zero crossings.
You also set up an interrupt on the INT0 signal to tell your program when the zero crossing occurds. You have set up the interrupt to only occur on the falling edge of the INT0 signal.
I'm guessing here but does the signal you have feeding into the INT0 pin indicate the phase of the incoming AC: in other words is the signal high on the positive phase and low on the negative phase? If so that you explain why you are only getting a trigger on the negative phase.
If you want to detect BOTH transitions, then you may need to use a different pin (in the RB4 to RB7 range) but the "interrupt on change" capability may be what you want.
Personally, I would not use interrupts at all for this and simply test the state of the input pin against its previous state and perform the action when I see a difference. I would also NOT have all of the delays in the debounce functions but I would move all of the button testing and debounce into a ISR based on a 1mSec timer. That way the debounce functions would never delay the main operations (which are working on a 20mSec cycle, assuming you are controlling a 50Hz signal) but you would always use whatever the delay value is at the time you detect an edge.
If you think about it, you are doing pretty much what I have describe anyway, but by introducing an interrupt you are complicating things unnecessarily.
Susan
 
Here is the circuit. I read somewhere that once the TRIAC is fired it conducts till the next zero cross and when zero cross occurs current through TRIAC will be 0 which is less than holding current and hence TRIAC turns OFF and in the next negative half cycle again the triac has to be fired for conduction. If Invert button in Proteus oscilloscope is pressed it shows correct waveform for chopped positive half cycle.


See, I am using bridge rectifier. The output freq of bridge rectifier is twice that of input AC frequency. For one AC cycle there will be two positive DC ripples. I think there is no need to toggle INTEDG detect on every ZC or should I toggle ?

When AC goes from negative to positive then a ZC occurs and voltage at the 4N37 input will cross the 0.6V required for forward bias. After this it will start conducting. At this time collector and INT0 pin in pulled low. So, edge detect should be high to low.

Next when AC goes from positive half cycle to negative half cycle another ZC occurs. This time also the DC ripple at 4N37 input rises from 0 to 0.6, 0.7, .... to max. So, again collector of 4N37 is pulled low. So again high to low transistion has to be detected.

So, according to my analysis what should happen is when sine wave goes from 0 to 1 degree say then INT0 detects high to low and after this we fire TRIAC and it conducts till 180 degrees or 179 degrees. Then when sine wave goes from 180 to 181 or 182 degrees then also INT0 has to detect high to low and trigger TRIAC so that TRIAC conducts till 360 degrees. But it is not happening like that.


Edit: See attached image. After every ZC a 2 ms delay is executed and then triac is fired. So, the wave shape should be as shown in image.

- - - Updated - - -

I was right. See these.

http://www.technology.niagarac.on.ca/people/mcsele/Colorgan.html

**broken link removed**

Chopping of AC is not proper in Proteus.
 

Attachments

  • phase angle control.png
    phase angle control.png
    74.3 KB · Views: 306
  • triac firing.png
    triac firing.png
    19.7 KB · Views: 265
Last edited:

For quick check of correct phase angle code operation, I would expect an oscilloscope waveform showing the AC, zero-crossing and gate control signal. The waveforms in post #1 don't reveal much information.
 
It seems that the pulses at RD0 are at both peaks of the AC wave. An ZC should be generated at the crossing of the zero axis so I think your ZC detection is problematic. See my simulation graph.

yellow line = AC sine wave
blue = at the gate of TRIAC
red = at RB0 input
green = at RD0 output

Allen
 

Attachments

  • milan rajik dimmer.PNG
    milan rajik dimmer.PNG
    105.2 KB · Views: 269
For quick check of correct phase angle code operation, I would expect an oscilloscope waveform showing the AC, zero-crossing and gate control signal. The waveforms in post #1 don't reveal much information.

@FvM

I will try to post the screenshots soon. The Proteus is giving problems. Within 5 seconds after simulation starts it gives some GMIN step error and exits.

I found another one. He has done something similar to me (atleast for the buttons).

https://avrprojects.info/avr-projects/digital-dimmer-using-atmega8/

Even this is not working but atleast the simulation runs fine without gmin step error for a long time but I only see sine wave. Buttons doesn't work.

@Allen6502

In your scope data the negative half wave is chopped properly but where is the chopped positive half cycle ?










Edit :

Latest code. Not working.


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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
unsigned char myFlags;
unsigned char milliSec = 9, counter = 0;
char mask[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
 
sbit ZC at myFlags.B0;
 
//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 500 ms
 
//Place/Copy this part in declaration section
void InitTimer1() {
  T1CON  = 0x31;
  TMR1IF_bit = 0;
  TMR1H = 0x0B;
  TMR1L = 0xDC;
  TMR1IE_bit = 1;
  INTCON = 0xC0;
}
 
void interrupt() {
     if (INT0IF_bit){
        ZC = 1;
        INT0IF_bit = 0;
     }
     
     if(TMR1IF_bit) {
          if(++counter == 2) {
                 counter = 0;
                 TMR1ON_bit = 0;
          }
          TMR1IF_bit = 0;
          TMR1H = 0x0B;
          TMR1L = 0xDC;
     }
}
 
void main() {
 
     ANSELA = 0x00;
     ANSELB = 0x00;
     ANSELC = 0x00;
     ANSELD = 0x00;
     ANSELE = 0x00;
     
     TRISA = 0xFF;
     TRISB = 0x07;
     TRISC = 0x00;
     TRISD = 0x00;
     
     PORTA = 0x00;
     PORTB = 0x00;
     PORTD = 0x00;
     
     LATA = 0x00;
     LATB = 0x00;
     LATC = 0xFF;
     LATD = 0x00;
 
     INTEDG0_bit = 0;
     INT0IF_bit = 0;
     INT0IE_bit = 1;
     PEIE_bit = 1;
     GIE_bit = 1;
     
     while (1){
 
            if((RB1_bit) && (!TMR1ON_bit)) {
                 Delay_ms(100);
                 if((RB1_bit) && (!TMR1ON_bit))
                    if(milliSec > 0)milliSec -= 1;
                    
                    LATC = mask[9 - milliSec];         //display fan speed value on 7 segment display (SSD)
                    
                    InitTimer1();                      //To create 1 sec delay between button presses
                                                    //When timer is running and less than 1 sec TMR0ON_bit will be 1 and hence button press detect code will be disabled
            }
            
            if((RB2_bit) && (!TMR1ON_bit)) {
                 Delay_ms(100);
                 if((RB2_bit) && (!TMR1ON_bit))
                    if(milliSec < 9)milliSec += 1;
                    
                    LATC = mask[9 - milliSec];       //display fan speed value on 7 segment display (SSD)
                    
                    InitTimer1();                   //To create 1 sec delay between button presses
                                                    //When timer is running and less than 1 sec TMR0ON_bit will be 1 and hence button press detect code will be disabled
            }
 
            if(ZC) {
                VDelay_Advanced_ms(milliSec, 4000);  //Fire TRIAC after 1, 2, 3, 4, 5, 6, 7, 8, 9, msec for RB1 button press and release
                                                     //Fire TRIAC after 9, 8, 7, 6, 5, 4, 3, 2, 1 msec for RB2 button press and release
                LATD.F0 = 1;
                Delay_us(250);
                LATD.F0 = 0;
                ZC = 0;
            }
     }
}

 

Attachments

  • ATMega Dimmer.rar
    30 KB · Views: 212
  • dimmer.png
    dimmer.png
    145.9 KB · Views: 255
Last edited:

I dont have proteus 8 so I am simulating using proteus 7.8 and that's what I got. Sorry if that's not the problems you have.

Allen
 
This is what I get.

Yellow = Load
Blue = Gate
Pink = RD0
Green = INT0


Edit:

I found this. It might be of some use for someone in solving my problem.

https://www.best-microcontroller-projects.com/microcontroller-controlled-light-dimmer.html

- - - Updated - - -

Modified the code a little but still not working.


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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
unsigned char milliSec = 9, counter = 0, i = 0;
char mask[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
 
//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 500 ms
 
//Place/Copy this part in declaration section
void InitTimer1() {
  T1CON  = 0x31;
  TMR1IF_bit = 0;
  TMR1H = 0x0B;
  TMR1L = 0xDC;
  TMR1IE_bit = 1;
  INTCON = 0xC0;
}
 
void interrupt() {
     if(INT0IF_bit){
            //Fire TRIAC after 1, 2, 3, 4, 5, 6, 7, 8, 9, msec for RB1 button press and release
            //Fire TRIAC after 9, 8, 7, 6, 5, 4, 3, 2, 1 msec for RB2 button press and release
          while(i != milliSec) {
              Delay_ms(1);
              i++;
          }
          i = 0;
          LATD.F0 = 1;
          Delay_us(250);
          LATD.F0 = 0;
 
        INT0IF_bit = 0;
     }
     
     if(TMR1IF_bit) {
          if(++counter == 2) {
                 counter = 0;
                 TMR1ON_bit = 0;
          }
          TMR1IF_bit = 0;
          TMR1H = 0x0B;
          TMR1L = 0xDC;
     }
}
 
void main() {
 
     ANSELA = 0x00;
     ANSELB = 0x00;
     ANSELC = 0x00;
     ANSELD = 0x00;
     ANSELE = 0x00;
     
     TRISA = 0xFF;
     TRISB = 0x07;
     TRISC = 0x00;
     TRISD = 0x00;
     
     PORTA = 0x00;
     PORTB = 0x00;
     PORTD = 0x00;
     
     LATA = 0x00;
     LATB = 0x00;
     LATC = 0xFF;
     LATD = 0x00;
 
     INTEDG0_bit = 0;
     INT0IF_bit = 0;
     INT0IE_bit = 1;
     PEIE_bit = 1;
     GIE_bit = 1;
     
     while (1){
 
            if((RB1_bit) && (!TMR1ON_bit)) {
                 Delay_ms(100);
                 if((RB1_bit) && (!TMR1ON_bit))
                    if(milliSec > 0)milliSec -= 1;
                    
 
                    
                    InitTimer1();                      //To create 1 sec delay between button presses
                                                    //When timer is running and less than 1 sec TMR0ON_bit will be 1 and hence button press detect code will be disabled
            }
            
            if((RB2_bit) && (!TMR1ON_bit)) {
                 Delay_ms(100);
                 if((RB2_bit) && (!TMR1ON_bit))
                    if(milliSec < 9)milliSec += 1;
 
                    InitTimer1();                   //To create 1 sec delay between button presses
                                                    //When timer is running and less than 1 sec TMR0ON_bit will be 1 and hence button press detect code will be disabled
            }
            
            LATC = mask[9 - milliSec];    //display fan speed value on 7 segment display (SSD)
     }
}

 

Attachments

  • waveforms.png
    waveforms.png
    138.6 KB · Views: 223
Last edited:

Don't put a delay in the ISR!
While the ISR is running the processor cannot do ANYTHING else.
I assume the greed trace comes from the output of the 4N37 (and why you keep covering up the changing circuit with the scope screen is beyond me - it just makes it hard to guess what is going on) which is driven by the bridge rectifier. Without knowing the voltage swing form the AC source and therefore the output of the rectifier, it seems very strange to me that the single to the INT0 pin is a square wave - I would expect it to be normally high (because of the pull-up R4) and then pulled down when the rectifier voltage got high enough.
I cannot understand why the top two traces show a negative part of the first cycle (and perhaps the last?) but not for the other cycles - what changed?
Also why is there a delay between the trigger from RD0 to the switching of the triac?
In other words, is the simulator (and I must admit I never trust simulators) working 100% or are there bugs that are sending you off on a false trail?
Susan
 
I know using delays inside ISR is not a good practise but my delays are smaller, max 9 ms. See, between two ZC's the duration is 10 ms and my delay inside ISR is only max 9 ms and so it won't cause any problem. I did that because there is a nasty 100 ms delay in button press detect code. When button is pressed at that time TRIAC firing code was not executing properly due to delay, So, I put the triac firing code in ISR and made sure it executes whenever these is a ZC. Now button debounce delay doesn't cause problem. But still my problem is not solved.

Here you go. The Circuit as image.

I cannot understand why the top two traces show a negative part of the first cycle (and perhaps the last?) but not for the other cycles - what changed?

Deficiency of resourses required for Proteus simulation. My system has only 4 GB RAM.
 

Attachments

  • phase angle control.png
    phase angle control.png
    74.3 KB · Views: 263

It has been a very long time since I have written code for the PIC18F family of devices and it was also using the XC8 compiler (therefore I know that syntax rather than the MikroC one - treat this a "pseudo-code"), but this is along the lines I was thinking about:
Code:
static int lastButtonStates;

// Define the number of times a pin must match before it is debounced
#define MAX_CHECKS 10
static volatile char states[MAX_CHECKS];
static volatile int index;
static volatile int buttonStates;

void Interrupt(void)
{
	char buttonBits;
	int i, j;

	if( TMR1IF)
	{
		TMR1IF = 0;		// Clear the interrupt flag
		TMR1 = 61536; 	// (65536 - 4000) reset the timer

		// Read in the current button values
		buttonBits = PORTB & 0x07;	// Read in Port B bits RB0 to RB2
		states[index++] = buttonBits;
		j = 0xff;
		for( i = 0; i <MAX_CHECKS; i++)
		{ j &= states[i]; }
		buttonStates = j;
		if( index >= MAX_CHECKS)
		{ index = 0; }
	}
}



// Within the main program
	char previousTrigger = 0;		// Last used state of the RB0 input
	
	index = 0;
	
	// Part of the initialisation section
	// Create a 1mSec clock
	T1CON = 0;
	TMR1 = 61536; // (65536 - 4000)
	TMR1IF = 0;
	TMR1IE = 1;
	T1CONbits.TMR1ON = 1;
	
	// In the main loop - check for a chage in the buttons states
	if( buttonStates != lastButtonStates)
	{
		// Work out which was different and in which direction
		// and take appropriate action
		if( (buttonStates && 0x02) == 0x02 then)
		{
			// Button RB1 is high so increment the counter
			if( milliSec < 10) milliSec++;
		}
		
		// Etc
		
		lastButtonStates = buttonStates
	}
	
	// Check to see if we need to trigger
	if( PORTBbits.RB0 != previousTrigger)
	{	
		// Capture the new state
		previousTrigger = PORTBbits.RB0;
		
		// Do whatever we need to as we have just seen an edge 
		// If you need to know if it was rising or falling then
		// it will be rising if PORTBbits.RB0 is not 1
	}
These are code snippets only - you wil need to add in all of the other code parts that make it work (setting the oscillator, port setup etc.).
The first part is the debounce code. It actually debounces the RB0 to RB2 pins at the same time. I know the RB0 pin does not need debouncing but there is no extra cost to include it and it makes the coding a little simpler.
The ISR is called every 1 mSec and checks to see if the input pins are in the same state for 10 consecutive interrupts. If not then corresponding the "buttonStates" states the way it was - otherwise it is reset to the new (now stable) setting.
The next bit is to initialise Timer 1 to interrupt every 1mSec. I assume you are still running with a 4MHz clock - you will need to adjust the TMR1 register setting if not.
within your main loop all you need to do is to check to see if any of the buttons (specifically RB1 and RB2) have changed state by comparing them with the last processed state. If one has changed then you can increment or decrement the timer value as you need.
Also within the main loop you can checkto see of RB0 has changed. (The buttonStates also captures this BUT with a delay of 10mSec - or whatever MAX_CHECKS is set to.) If it has changed then you can detect if it is a rising or falling edge and take the appropriate action.
There are no delays in the ISR and so the main code will run as fast as it can. Therefore it can respond within a few machine cycles of any change - certainly fast enough for your purpose.
If you need other delays within your processing of any RB0 transition, then they can all sit within the main code (or at least NOT at ISR level) and you may be able to extend the 1mSec ISR to give you whatever mSec-resolution delays you need.
Hope this gives you some ideas so that you can clean up your code.
 
Thank you Susan. I will try to implement your codei in mikroC PRO PIC but here is what actually I want. He has done it using ATMEGA16. He has a button which changes the firing angle. There is a link in the page which opens google docs and .c file can be downloaded. It is very simple code. It is written in CodeVisionAVR.

He is getting correct waveforms.

https://www.youtube.com/watch?v=udwPARinbys

I will implement your code and the code in the above link separately and see what happens and I will update here.
 

After some experimenting with different TRIAC models one worked for VSIN value = 50V 50Hz. I have used a pulse instead of ZC and a delay of 2ms is used for the pulse. The pulse has twice the frequency (100 Hz) of 50V AC 50 HHz. Proteus 8.1 SP1 file attached. Now I will try to do the microcontrolled based firing.

- - - Updated - - -

@FvM

Please provide me a solution. I am attaching new version. Now buttons work. I have used INT1 and INT2 for buttons and INT0 for ZC. LATD0 fires gate. The 7 segment display displays values 0 - 9. The pink wave is gate trigger. It shifts between two ZC when buttons are pressed. Only the triac signal is not correct even though triac is firing properly.

Complete project files + Proteus 8.1 SP1 file attached.

See image 2. 3 signals are correct. Triac signal is not correct.

- - - Updated - - -

Edit:

New proteus file attached. Use .hex file from post #15. I changed TRIAC model in Proteus. Now positive half cycle is chopping properly with button press but negative half cycle has vanished.

- - - Updated - - -

I used a pulse tool to inject gate trigger pulses of 200 Hz and magically both +ve and -ve chopped waves appeared. Then I again changed the pulse freq to 100 Hz and still the wave forms were ok. Is it a proteus bug ?

- - - Updated - - -

Edit. How in image 3 even though there is no gate trigger for negative half wave the negative half wave is chopping ?



Edit: According to code (rev 3) gate is triggering only at 0 degree + x ms. It is not tiggering at 180 + degrees. That is why negative wave is not chopping.
 

Attachments

  • triac control.png
    triac control.png
    104.5 KB · Views: 332
  • triac control.rar
    19.6 KB · Views: 190
  • Dimmer rev1.rar
    55.1 KB · Views: 183
  • triac wave err.png
    triac wave err.png
    132.4 KB · Views: 245
  • partly working.rar
    22.2 KB · Views: 181
  • Dimmer rev3.rar
    54.4 KB · Views: 198
  • somewhat working.png
    somewhat working.png
    86.2 KB · Views: 234
New proteus file attached. Use .hex file from post #15. I changed TRIAC model in Proteus. Now positive half cycle is chopping properly with button press but negative half cycle has vanished.
Yes, that's expectable because only the positive cycle is triggered.

Obviously, the zero crossing waveform (green trace) doesn't fit a full wave rectifier output. Something is wrong in your simulation, may be the 4N37 model.
 
@FvM

Yes, you are right and Susan was also right. The was no frint at 180+ degrees. I changed the code. I added toggle edge detect in ISR and now finally it worked fine.

Here is working code + new Proteus file.

Yes, I don't know why green signal is not correct.

Now I will use Timers and implement multi triac control.
 

Attachments

  • Dimmer rev4.rar
    54.6 KB · Views: 203
  • working finally.png
    working finally.png
    144 KB · Views: 226
@FvM

Why 4N37 is not giving correct pulses ? AC freq is 50 Hz and output of bridge rectifier should be double the input AC freq that is 100 Hz. So, the 4N37 output should go high to low twice per cycle of AC. Why it is not happening ? Or is it working fine at your side ?
 

Why 4N37 is not giving correct pulses ? AC freq is 50 Hz and output of bridge rectifier should be double the input AC freq that is 100 Hz. So, the 4N37 output should go high to low twice per cycle of AC. Why it is not happening ? Or is it working fine at your side ?
I'm not using Proteus 8 and can't check your simulation setup. But obviously the 4n37 output waveform (about 50 Hz square wave with 50 percent duty cycle) is different from the expectable 100 Hz pulses. It may be something trivial like interchanged pins in the simulation model. You can find out by e.g. reviewing a SPICE netlist of the design.
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top