View previous topic :: View next topic |
Author |
Message |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Jul 01, 2013 4:28 pm |
|
|
For the MOC3020 - i would use 10 us LED drive to insure repeatable firing , especially for good "late in the cycle" operation.
The MOC3020 is a very low cost device with a SLOW response for guaranteed activation.
For really FAST triggering - i would consider a ferrite transformer coupled circuit, and a comparator form of Z cross detector.
Let me guess: this is a hobbyist/student endeavor? |
|
|
shams
Joined: 30 Jun 2013 Posts: 11
|
|
Posted: Tue Jul 02, 2013 12:17 am |
|
|
Ttelmah wrote: | Because you want to adjust how long _after_ the zero cross, you fire the TRIAC.....
...
|
So is it that...I can fire the triac through Timer INT without firing in while loop?
Sorry, I'm asking so many questions.
Code: | while (1) {
if (ZC)
{
output_high(PIN_C0);
...
}
} |
Can it be used in this way...:
Code: |
#include <16F886.h>
#fuses HS
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin NOT enabled
#FUSES BROWNOUT //Reset when brownout detected
#use delay(clock=20M)
#define DIM_LEVEL 65535
int1 ZC=FALSE;
#INT_EXT //External Interrupt
void EXT_isr(void)
{
output_low(PIN_C0); //make sure gate is OFF
set_timer0(DIM_LEVEL); //preload_time into Timer0
enable_interrupts(INT_TIMER0); //start Timer0
ZC = TRUE;
}
#int_TIMER0
void TIMER0_isr(void)
{
if (ZC) //execute if zero crossing occures
{
set_timer0(0); //stop Timer0
output_high(PIN_C0); //turn the gate ON
delay_uS(100);
output_low(PIN_C0); //turn the gate OFF
clear_interrupt(INT_TIMER0); //clear Timer0
ZC = FALSE;
}
}
void main( void ) {
//drive all pins low, except B0, set as input
output_b(0);
output_c(0);
output_float(PIN_B0);
setup_timer_0( T0_INTERNAL | T0_DIV_1 );
//ext_int_edge(H_TO_L); //set the falling edge to trigger on the ZC signal
ext_int_edge(L_TO_H); //set the rising edge to trigger on the ZC signal
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while (1) {
}
} |
Last edited by shams on Wed Jul 03, 2013 1:26 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19620
|
|
Posted: Wed Jul 03, 2013 12:44 am |
|
|
You are still 'missing the point' about TRIAC firing. The duration of the pulse has nothing whatsoever to do with how long the TRIAC is on.
It is 'when' the pulse is relative to the zero crossing point that controls the 'on' duration.
You need to display the following in a fixed pitch font:
Code: |
|-------------------|-------------------|------ zero crossing points
-|-------------------|-------------------|----- firing pulse for 'full on'
-------------------|-------------------|------- firing pulse for 'minimum'
----------|-------------------|---------------- firing pulse for '50%'
|
Now, the firing pulse is just a pulse. For your rather slow TRIAC, 10uSec ideal. Fast TRIAC's, have nSec pulse widths required.
Once fired, the TRIAC itself, remains on, for the rest of the mains half cycle.
You can't fire the TRIAC, till it has a little voltage across it, so you cannot fire it 'at' the zero crossing point.
For 50Hz mains, a 'half cycle', is 10mSec.
So fire it 1mSec after the zero point, and it'll be on 90% of the time.
Fire it 9mSec after the zero point, and it'll be on just 10% of the time.
Fire it 5mSec after the zero point, and it'll be on 50% of the time.
So (logic only):
Code: |
Detect zero - start timer - set the time to time-out, based upon the power you want. Longer time - up to10mSec = lower power.
Detect timer time-out, - fire the pulse. Go back to waiting for the zero detection.
|
You have to get away from thinking of the actual 'pulse' having any relationship to how long the TRIAC is 'on'. It is _when_ the pulse happens, that determines this, nothing else.
Best Wishes |
|
|
shams
Joined: 30 Jun 2013 Posts: 11
|
|
Posted: Wed Jul 03, 2013 1:33 am |
|
|
Thank you, Ttelmah. I changed the code as per your suggestion.
Kindly see above your post. Do you think the concept is right? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Jul 03, 2013 2:33 am |
|
|
You're the with the hardware in front of you.
Tell us, does it do what you expect or not?
You've got this line, so I'm assumng that you really have a 20MHz clock. Code: | #use delay(clock=20M) |
That's 5M instruction cycles per second.
You've then set up a timer0 delay to count down with these lines. Code: | #define DIM_LEVEL 65535
.........
set_timer0(DIM_LEVEL); //preload_time into Timer0
|
How long do you think the delay might be?
Mike
PS You are also expecting us to remember what your old code was after you've editted an old post.
I've slept since then and suggest you simply post your new code, leaving the original post intact.
EDIT
At your level you'ld be better off using the CCS delay functions throughout.
That way you could write very short simple code 'til you've learnt the basics. |
|
|
shams
Joined: 30 Jun 2013 Posts: 11
|
|
Posted: Wed Jul 03, 2013 2:53 am |
|
|
Mike Walne wrote: | ...
I've slept since then and suggest you simply post your new code, leaving the original post intact.
... |
Thanks Mike. I'll follow that next time.
I'm expecting that Triac will be fired after the "waiting time" set in Timer0. But it's not working in my expected way. I really need to understand the timer math.
Do you mind to share the calculation for timer0 delay?
EDIT:
This is the math I discovered.
((1/(MainsFreq*2)) / 256) / (1/(Crystal Freq/4)) = TimerCount
For 50Hz Mains @ 20Mhz Clock
1/(50Hz*2) = 10ms
10ms/256 = 39us
1/(20MHz/4) = 0.2us
39us/0.2us = 195
So if I got the math right then my max delay will be 256-195=61...is it? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Jul 03, 2013 3:41 am |
|
|
It would help if you told us what your code:-
1) Should do.
2) Does do.
3) Does not do.
There are just too many things you don't understand.
I'm suggesting you do soemthing REALLY simple, as a learning exercise.
I'm assuming that you're hardware is OK, and you can do a simple 1Hz LED flasher at the correct speed.
THEN
Do a forever loop:-
1) Wait for zero cross.
2) Wait 5ms (i.e. delay_ms(5).
3) Fire Triac.
4) Loop back to (1)
Work on the KISS principal.
Do not use interrupts etc.
The code for the entire loop should be no more than 6 or 7 lines!
Should fire Triac with 50% duty.
Get to the stage where something works as expected, learn and make progress.
Mike |
|
|
shams
Joined: 30 Jun 2013 Posts: 11
|
|
Posted: Wed Jul 03, 2013 4:27 am |
|
|
Thanks once again.
Actually my HW and code both works without the Timer INT. But I would like to implemen Timer INT since I'll be using an ADC to change the delay.
Working code (without Timer INT):
Code: |
#include <16F886.h>
#fuses XT
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin NOT enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#use delay(int=4000000)
int1 ZC=FALSE;
#INT_EXT //External Interrupt
void EXT_isr(void)
{
if(!ZC){ //check if gate is really OFF
output_low(PIN_C0);
}
ZC = TRUE;
}
void main( void ) {
//drive all pins low, except B0, set as input
//output_a(0);
output_b(0);
output_c(0);
output_float(PIN_B0);
ext_int_edge(L_TO_H); //set the rising edge to trigger on the ZC signal
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while (1) {
if (ZC)
{
delay_ms(6); //set the luminosity 50%
output_high(PIN_C0);
delay_uS(100);
output_low(PIN_C0);
ZC = FALSE;
}
}
}
|
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Jul 03, 2013 7:06 am |
|
|
I was anticipating you might work entirely without any interrupts.
However:-
1) Are you now saying that your latest code gives you the brightness you expect?
2) Can you change the brightness by varying the value in the delay_ms(xx) statement?
Yes. I understand what it is you are trying to do, but you need to work in SMALL manageable steps.
Get one section working properly, then move on.
Mike |
|
|
shams
Joined: 30 Jun 2013 Posts: 11
|
|
Posted: Wed Jul 03, 2013 8:48 am |
|
|
Hi Mike, answer of your questions:
1. Yes, I get the expected brightness
2. Yes, brightness is varying by the value of delay_ms (0-10ms).
However, adding ADC option changes the whole thing...i.e lamp starts blinking...
I read a lot about Timer INT and the help from you guys, seems I'm close to the concept. But one thing I still couldn't discover, it is the timer prescaller thing.
Code: |
setup_timer_0( T0_INTERNAL | T0_DIV_1 );
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
..etc.
|
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Jul 03, 2013 9:40 am |
|
|
Good, you're making progress
Quote: | Hi Mike, answer of your questions:
1. Yes, I get the expected brightness
2. Yes, brightness is varying by the value of delay_ms (0-10ms). |
BUT:-
Quote: | However, adding ADC option changes the whole thing...i.e lamp starts blinking... |
a) How many new things are you trying to introduce at once?
b) Are you trying to use the timers?
c) Are you certain that your ADC values are stable?
I'm asking these questions in response to
Quote: | I read a lot about Timer INT and the help from you guys, seems I'm close to the concept. But one thing I still couldn't discover, it is the timer prescaller thing.
Code:
setup_timer_0( T0_INTERNAL | T0_DIV_1 );
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
..etc.
|
Mike |
|
|
shams
Joined: 30 Jun 2013 Posts: 11
|
|
Posted: Wed Jul 03, 2013 10:19 am |
|
|
Thanks buddy.
I'm not trying ADC at the moment and my concentration is timer thing. I think I need the Tick approx 60* per second. I need your help to understand the calculation.
Code: | setup_timer_0(T0_INTERNAL|T0_8_BIT|T0_DIV_64); |
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Jul 03, 2013 11:04 am |
|
|
Sorry for being so pedestrian, but you keep trying to run before you can crawl, let alone walk.
What do you actually want the timer_0 to do for you?
I need to know before I can offer guidance.
Mike |
|
|
|