|
|
View previous topic :: View next topic |
Author |
Message |
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
Problem when use Zero crossing detect without ext interrupt |
Posted: Wed Mar 23, 2016 7:30 pm |
|
|
Hi everybody.
I'm doing a project using Zero crossing detect function to driver Triac.
In this circuit, I don't use ext interrupt pin to detect an ac zero point, so I'm using a timer interrupt to check an ac zero point condition, but I can't detect although i set an timer interrupts interval is fast.
I also checked the AC zero point with oscilloscope, it have a low pulse when detect AC main voltage drop to 0v.
My project is using PIC16LF1455 to interface with PC via USB ports, CCS C ver 5.051.
And here is my program:
Code: |
#define USE_USB_SERIAL_NUMBER
#include "ex_usb_common.h"
#include "stdlib.h"
unsigned int8 count_t1=0;
unsigned int16 count_t0=0;
unsigned int1 timeout=0;
unsigned int1 light_on=0;
unsigned int8 delay_time=0;
// you can change the tx and rx packet sizes here.
// in order to be compatible with hiddemo.exe, these values must be 2.
#define USB_CONFIG_HID_TX_SIZE 10
#define USB_CONFIG_HID_RX_SIZE 10
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic16f_usb.h> //Microchip PIC16Fxxxx hardware layer for usb.c
#include <usb_desc_hid.h> //USB Configuration and Device descriptors for this UBS device
#include <usb.c> //handles usb setup tokens and get descriptor reports
#if defined(USE_USB_SERIAL_NUMBER)
#serialize(id=USB_STRING_DESC, unicode=3, prompt="Serial Number")
#endif
#define relay1 PIN_C5
#define relay1 PIN_C2
#define light PIN_C4
int8 out_data[USB_CONFIG_HID_TX_SIZE];
int8 in_data[USB_CONFIG_HID_RX_SIZE];
unsigned int1 alert_pc=0, crimp=1;
#int_timer1
void ngat_delay_check(void)
{
set_timer1(5535);
count_t1++;
if(count_t1>=100)
{
count_t1=0;
timeout=1;
}
}
#int_timer0
void ngat_zcd(void)
{
set_timer0(248);
if(input(PIN_C1)==0 && light_on==1)
{
delay_ms(delay_time);
output_high(light);
delay_ms(1);
output_low(light);
}
}
//================================================================================================================================
//------------------------------------- MAIN PROGRAM -------------------------------------------------------------------
//================================================================================================================================
void main(void)
{
delay_ms(100);
usb_init_cs();
delay_ms(100);
output_low(light);
set_timer1(5535); // setup timer1: 40ms
setup_timer_1 (T1_INTERNAL|T1_DIV_BY_8);
set_timer0(248);
setup_timer_0 (T0_INTERNAL|T0_DIV_256|T0_8_BIT);
enable_interrupts(int_timer0);
enable_interrupts(global);
for(;;)
{
usb_task();
if (usb_enumerated())
{
//-----------------------------------------------------------------------------------
//-------------------------- SEND ACK TO PC ----------------------------------------
//-----------------------------------------------------------------------------------
if(input(PIN_A4)==0 && crimp==1)
{
delay_ms(10);
while(input(PIN_A4)==0);
out_data[0] = '$';
out_data[1] = 'T';
out_data[2] = 'A';
out_data[3] = 'K';
out_data[4] = 'E';
out_data[5] = '0';
out_data[6] = '0';
out_data[7] = '0';
out_data[8] = '0';
out_data[9] = '#';
usb_put_packet(USB_HID_ENDPOINT, out_data, USB_CONFIG_HID_TX_SIZE, USB_DTS_TOGGLE);
output_high(relay1);
light_on=1;
timeout=0;
count_t1=0;
crimp=0;
enable_interrupts(int_timer1);
clear_interrupt(int_timer1);
}
//-----------------------------------------------------------------------------------
//-------------------------- SEND REQUEST TO NODE ----------------------------------
//-----------------------------------------------------------------------------------
if (usb_kbhit(USB_HID_ENDPOINT))
{
usb_get_packet(USB_HID_ENDPOINT, in_data, USB_CONFIG_HID_RX_SIZE);
if(in_data[0]=='$' && in_data[1]=='S' && in_data[2]=='E'&& in_data[3]=='T'
&& in_data[4]=='T' && in_data[5]=='I' && in_data[6]=='M' && in_data[7]=='E'&& in_data[9]=='#')
{
delay_time= in_data[8];
}
else if( in_data[0]=='$' && in_data[9]=='#')
{
out_data[0] = '$';
out_data[1] = 'O';
out_data[2] = 'K';
out_data[3] = '0';
out_data[4] = '0';
out_data[5] = '0';
out_data[6] = '0';
out_data[7] = '0';
out_data[8] = '0';
out_data[9] = '#';
usb_put_packet(USB_HID_ENDPOINT, out_data, USB_CONFIG_HID_TX_SIZE, USB_DTS_TOGGLE);
}
else
{
out_data[0] = '$';
out_data[1] = 'N';
out_data[2] = 'G';
out_data[3] = '0';
out_data[4] = '0';
out_data[5] = '0';
out_data[6] = '0';
out_data[7] = '0';
out_data[8] = '0';
out_data[9] = '#';
usb_put_packet(USB_HID_ENDPOINT, out_data, USB_CONFIG_HID_TX_SIZE, USB_DTS_TOGGLE);
}
}
//-----------------------------------------------------------------------------------
//-------------------------- SEND WARNING DISCONECT----------------------------------
//-----------------------------------------------------------------------------------
if(timeout==1)
{
output_low(relay1);
output_low(light);
light_on=0;
timeout=0;
count_t1=0;
crimp=1;
disable_interrupts(int_timer1);
clear_interrupt(int_timer1);
}
}
}
}
|
Please help me to solve this error.
Thanks you _________________ Begin Begin Begin !!! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Wed Mar 23, 2016 8:08 pm |
|
|
Please explain how you detect the actual zero cross of the AC mains. What hardware are you using and why aren't you using known, time tested zero cross detetcion? Also just HOW do you think a timer will function as a zero cross detector?
I've used optocouplers for 3 decades for zero cross detection so I'm curious to understand your idea.
Jay |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Thu Mar 24, 2016 3:34 am |
|
|
Big problem straight away, is using delay_ms in the interrupt.
Because of this, interrupts will be disabled in all delays in the external code. Result not what you want.....
Since the interrupt is being called (nominally) every 2048 instructions, consider doing the delay by just waiting a few interrupts.....
You don't show us your clock rates.
Honestly, make your tick (say) every 0.5mSec using timer2 (this is the only timer that can generate an exact 'interval', and automatically repeat this). Then have a state machine in the timer, which looks for the falling edge, and then looks for the rising edge of your pulse. On the rising edge turn your output on, and then two ticks later (so no delays in the interrupt), turns it back off.
If you look at your timings, triggering on the falling edge (as you currently do), is likely to have your pulse finished _before_ the actual zero crossing, so the triac will turn on, and immediately off..... |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Thu Mar 24, 2016 7:07 pm |
|
|
Thanks for your suggestions, I'm careless when using delay in it, really this's a big bug :D
In my program running with system is 48Mhz for USB interface.
In your solutions, i don't understand why to check both edge of pulse. I think only check when the pulse to pin( detect zero point) to set delay time -> turn on triac-> set delay time -> turn off triac.
I'm changed the program to replace the delay functions by counter in timer0 interrupts( when detect a zero point-> delay 1ms-> turn triac-> delay 1ms -> off triac) but the result not change, may be an error in this program because now i don't have an oscilloscope to check waveform.
Code: |
#define USE_USB_SERIAL_NUMBER
#include "ex_usb_common.h"
#include "stdlib.h"
unsigned int8 count_t1=0;
unsigned int16 count_t01=0, count_t02=0;
unsigned int1 timeout=0;
unsigned int1 light_on=0;
unsigned int8 delay_time=0;
unsigned int1 alert_pc=0, crimp=1;
unsigned int1 triac_trigger=0;
unsigned int1 triac_on=0;
// you can change the tx and rx packet sizes here.
// in order to be compatible with hiddemo.exe, these values must be 2.
#define USB_CONFIG_HID_TX_SIZE 10
#define USB_CONFIG_HID_RX_SIZE 10
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic16f_usb.h> //Microchip PIC16Fxxxx hardware layer for usb.c
#include <usb_desc_hid.h> //USB Configuration and Device descriptors for this UBS device
#include <usb.c> //handles usb setup tokens and get descriptor reports
#if defined(USE_USB_SERIAL_NUMBER)
#serialize(id=USB_STRING_DESC, unicode=3, prompt="Serial Number")
#endif
#define relay1 PIN_C5
#define relay1 PIN_C2
#define light PIN_C4
int8 out_data[USB_CONFIG_HID_TX_SIZE];
int8 in_data[USB_CONFIG_HID_RX_SIZE];
#int_timer0 // 0.1ms
void ngat_zcd(void)
{
set_timer0(251);
if( (input(PIN_C1)==0) && (light_on==1) && (triac_trigger==0) )
{
triac_trigger=1;
while(input(PIN_C1)==0);
}
if(triac_trigger==1)
{
if(triac_on==0) count_t01++;
if(count_t01==10)
{
count_t01=0;
output_high(light);
triac_on=1;
}
if(triac_on==1) count_t02++;
if(count_t02==10)
{
count_t02=0;
output_low(light);
triac_on=0;
triac_trigger=0;
}
}
}
//-------------------------------------------------------------------------
#int_timer1 // 40ms
void ngat_delay_check(void)
{
set_timer1(5535);
count_t1++;
if(count_t1>=100)
{
count_t1=0;
timeout=1;
}
}
//================================================================================================================================
//------------------------------------- MAIN PROGRAM -------------------------------------------------------------------
//================================================================================================================================
void main(void)
{
delay_ms(100);
usb_init_cs();
delay_ms(100);
output_low(light);
set_timer0(251); // setup timer0: 0.1ms
setup_timer_0 (T0_INTERNAL|T0_DIV_256|T0_8_BIT);
enable_interrupts(int_timer0);
set_timer1(5535); // setup timer1: 40ms
setup_timer_1 (T1_INTERNAL|T1_DIV_BY_8);
enable_interrupts(global);
for(;;)
{
usb_task();
if (usb_enumerated())
{
//-----------------------------------------------------------------------------------
//-------------------------- SEND ACK TO PC ----------------------------------------
//-----------------------------------------------------------------------------------
if(input(PIN_A4)==0 && crimp==1)
{
delay_ms(10);
while(input(PIN_A4)==0);
out_data[0] = '$';
out_data[1] = 'T';
out_data[2] = 'A';
out_data[3] = 'K';
out_data[4] = 'E';
out_data[5] = '0';
out_data[6] = '0';
out_data[7] = '0';
out_data[8] = '0';
out_data[9] = '#';
usb_put_packet(USB_HID_ENDPOINT, out_data, USB_CONFIG_HID_TX_SIZE, USB_DTS_TOGGLE);
output_high(relay1);
light_on=1;
timeout=0;
count_t1=0;
crimp=0;
enable_interrupts(int_timer1);
clear_interrupt(int_timer1);
}
//-----------------------------------------------------------------------------------
//-------------------------- SEND REQUEST TO NODE ----------------------------------
//-----------------------------------------------------------------------------------
if (usb_kbhit(USB_HID_ENDPOINT))
{
usb_get_packet(USB_HID_ENDPOINT, in_data, USB_CONFIG_HID_RX_SIZE);
if(in_data[0]=='$' && in_data[1]=='S' && in_data[2]=='E'&& in_data[3]=='T'
&& in_data[4]=='T' && in_data[5]=='I' && in_data[6]=='M' && in_data[7]=='E'&& in_data[9]=='#')
{
delay_time= in_data[8];
}
else if( in_data[0]=='$' && in_data[9]=='#')
{
out_data[0] = '$';
out_data[1] = 'O';
out_data[2] = 'K';
out_data[3] = '0';
out_data[4] = '0';
out_data[5] = '0';
out_data[6] = '0';
out_data[7] = '0';
out_data[8] = '0';
out_data[9] = '#';
usb_put_packet(USB_HID_ENDPOINT, out_data, USB_CONFIG_HID_TX_SIZE, USB_DTS_TOGGLE);
}
else
{
out_data[0] = '$';
out_data[1] = 'N';
out_data[2] = 'G';
out_data[3] = '0';
out_data[4] = '0';
out_data[5] = '0';
out_data[6] = '0';
out_data[7] = '0';
out_data[8] = '0';
out_data[9] = '#';
usb_put_packet(USB_HID_ENDPOINT, out_data, USB_CONFIG_HID_TX_SIZE, USB_DTS_TOGGLE);
}
}
//-----------------------------------------------------------------------------------
//-------------------------- SEND WARNING DISCONECT----------------------------------
//-----------------------------------------------------------------------------------
if(timeout==1)
{
output_low(relay1);
output_low(light);
light_on=0;
timeout=0;
count_t1=0;
crimp=1;
triac_trigger=0;
disable_interrupts(int_timer1);
clear_interrupt(int_timer1);
}
}
}
}
|
Thanks. _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Fri Mar 25, 2016 2:03 am |
|
|
OK. Lets step back a bit.
First thing to remember is you can't trigger a TRIAC, till you have passed the zero point.
Looking at your waveform, the pulse is low for about a mSec. So it is pointless (and will degrade performance massively), to try to sample 'too fast'. I'd suggest 0.5mSec would be much better. So:
setup_timer_2(T2_DIV_BY_4, 149, 10);
This gives /6000 from the Fcy (4*150*10), so will trigger the timer2 interrupt every 0.5mSec. (48000000/(4*4*150*10))
Change the interrupt enable for timer2.
Then
Code: |
#INT_TIMER2
void half_msec(void)
{
static int8 pulse_ctr=0;
static int1 pulse_seen=FALSE;
if (light_on)
{
//We only want to perform tests if the light is enabled
if (input(PIN_C1)==0)
{
pulse_seen=TRUE;
return; //exit ASAP
}
if (pulse_seen)
{
//will get here just after the pulse _rising_ edge
output_high(light); //start the TRIAC pulse
pulse_seen=FALSE;
return; //and again exit
}
if (++pulse_ctr<2) //wait for 2 interrupts
return; //again get out
//Now turn off the pulse and reset for the next one
output_low(light); //and pulse off
pulse_ctr=0;
}
else
output_low(light); //ensure light is off
}
|
This will pulse the 'light' signal for 1mSec just after the rising edge of the zero detector.
The 'off' for 'light' at the end, is to handle the situation where the main code turns off the light, while the code is 'mid pulse'. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Mar 25, 2016 9:30 am |
|
|
simple observation:
your zero cross detector circuit is not up the job.
not even close
and the mysterious H1 component makes no sense at all.
secondly:
although cheap and ubiquitous ( and CRUDE) - the SCR and TRIAC are not the only devices that can be used as an AC modulator.
You never mention what your LOAD is or the power range IS -that you wish to modulate.
code is only part of your problem. Good code still won't fix bad hardware design......... |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sat Mar 26, 2016 1:49 am |
|
|
Ttelmah wrote: | OK. Lets step back a bit.
First thing to remember is you can't trigger a TRIAC, till you have passed the zero point.
Looking at your waveform, the pulse is low for about a mSec. So it is pointless (and will degrade performance massively), to try to sample 'too fast'. I'd suggest 0.5mSec would be much better. So:
setup_timer_2(T2_DIV_BY_4, 149, 10);
This gives /6000 from the Fcy (4*150*10), so will trigger the timer2 interrupt every 0.5mSec. (48000000/(4*4*150*10))
Change the interrupt enable for timer2.
Then
Code: |
#INT_TIMER2
void half_msec(void)
{
static int8 pulse_ctr=0;
static int1 pulse_seen=FALSE;
if (light_on)
{
//We only want to perform tests if the light is enabled
if (input(PIN_C1)==0)
{
pulse_seen=TRUE;
return; //exit ASAP
}
if (pulse_seen)
{
//will get here just after the pulse _rising_ edge
output_high(light); //start the TRIAC pulse
pulse_seen=FALSE;
return; //and again exit
}
if (++pulse_ctr<2) //wait for 2 interrupts
return; //again get out
//Now turn off the pulse and reset for the next one
output_low(light); //and pulse off
pulse_ctr=0;
}
else
output_low(light); //ensure light is off
}
|
This will pulse the 'light' signal for 1mSec just after the rising edge of the zero detector.
The 'off' for 'light' at the end, is to handle the situation where the main code turns off the light, while the code is 'mid pulse'. |
Hi
I changed to the program of you, the triac turn on, but the light is blink.
The load in this circuit is 220VAC Led bulb (I opened the cover and show it using an RC power supply).
Main purpose I want to detect a zero point to control phase, so make an dimmer light.
I think your programs don't change a delay time before turn on the triac.
I will check it again.
Thanks you. _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Sat Mar 26, 2016 2:48 am |
|
|
You can change time, by changing the count before the TRIAC is enabled.
Code: |
static int8 pulse_ctr=0;
static int1 pulse_seen=FALSE;
static int8 count=0;
if (light_on)
{
//We only want to perform tests if the light is enabled
if (input(PIN_C1)==0)
{
pulse_seen=TRUE;
count=time;
return; //exit ASAP
}
if (pulse_seen)
{
//will get here just after the pulse _rising_ edge
if (count--==0)
{
output_high(light); //start the TRIAC pulse
pulse_seen=FALSE;
}
return; //and again exit
}
//rest unchanged
|
Then change the value in 'time' in your main code. Lower number = higher power. 0=full
Blinking suggests you may have an interference problem from the TRIAC, or something else wrong in the code. |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sat Mar 26, 2016 4:12 am |
|
|
Thanks for your suggestions.
I have changed the program and set time (count=8) to test.
The light is bright lower but when i tried sometimes, the triac is broken (T1 ,T2, and gate are shorted).
Maybe an error in this triac driver circuit?
If anyone knows more about these problems, pls help me.
Thanks. _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Sat Mar 26, 2016 5:21 am |
|
|
Without looking through all your circuit bits, I don't on the triac circuit see any snubbing (series resistor and mains rated capacitor across the triac). This is needed, or if there is any inductive component in the circuit (even a lamp has a small inductance), it will kill the triac). Also there should be a resistor from the gate to the bottom of the triac to ensure it switches off properly.
The circuit here:
<http://forum.arduino.cc/index.php?topic=51671.0>
Shows these parts, but then also read, and see why there are problems if you try to use this circuit to dim..... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sat Mar 26, 2016 5:22 am |
|
|
You need to disconnect the PIC from your TRIAC control circuitry. Apply +3 volts to the transistor driver and see if the AC lamp lights fully. Also write a simple 'LED toggle' program and see if the I/O pin of the PIC does indeed go zero, 3 volts, zero, 3 volts. If it does then the PIC is OK.
If you read the TI version of the MOC3020, they do show you acceptable parts for various loads. Your choice of transistor driver base bias resistors may not be correct.Reconnect to the PIC and running that flashing LED program ,confirm the collector is going 3v,0v,3v,0v. I would have used the MOC3023 and directly driven from the PIC as it saves components, wiring problems, cheaper and PIC can easily power it.
Bottom line, you need to 'breakdown' your project into smaller sections, test each, decide which is faulty then repair as required.
Jay |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sat Mar 26, 2016 5:53 am |
|
|
Ttelmah wrote: | Without looking through all your circuit bits, I don't on the triac circuit see any snubbing (series resistor and mains rated capacitor across the triac). This is needed, or if there is any inductive component in the circuit (even a lamp has a small inductance), it will kill the triac). Also there should be a resistor from the gate to the bottom of the triac to ensure it switches off properly.
The circuit here:
<http://forum.arduino.cc/index.php?topic=51671.0>
Shows these parts, but then also read, and see why there are problems if you try to use this circuit to dim..... |
Thanks for your suggestion.
Really a first time i tried with triac. Im looking on the internet the schematic to driver TRIAC BTA12 using MOC3020, load is led bulb 220VAC-15W ( using RC type power supply for led, dont using a switching power supply). And I think load isnt inductance sothat I dont design a snubber, maybe an error, i'll change with this method.
+ Triac : [url] http://www.st.com/web/catalog/sense_power/FM144/CL1221/SC124/PF76115 [/url]
+ MOC3020:
http://www.futurlec.com/LED/MOC3020a.shtml
Thanks you. _________________ Begin Begin Begin !!! |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sat Mar 26, 2016 8:04 pm |
|
|
temtronic wrote: | You need to disconnect the PIC from your TRIAC control circuitry. Apply +3 volts to the transistor driver and see if the AC lamp lights fully. Also write a simple 'LED toggle' program and see if the I/O pin of the PIC does indeed go zero, 3 volts, zero, 3 volts. If it does then the PIC is OK.
If you read the TI version of the MOC3020, they do show you acceptable parts for various loads. Your choice of transistor driver base bias resistors may not be correct.Reconnect to the PIC and running that flashing LED program ,confirm the collector is going 3v,0v,3v,0v. I would have used the MOC3023 and directly driven from the PIC as it saves components, wiring problems, cheaper and PIC can easily power it.
Bottom line, you need to 'breakdown' your project into smaller sections, test each, decide which is faulty then repair as required.
Jay |
Thanks for your suggestions.
In this circuit, I also tested driver triac from MOC3020, it driver triac on/off right when using a fixed pulse, not using zero cross detect, so I think the driver for triac using MOC and transistor is OK.
But when i tried to control with zero cross detect and ouput pulse to triac, have a problems when triac is borken.
Thanks you. _________________ Begin Begin Begin !!! |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sat Mar 26, 2016 8:33 pm |
|
|
Hi.
I tried with snuber for triac load but the result dont change.
I use capacitor ceramic 223K-1200V(22nf) series with R 100 0.25W, and resistor 330 0.25w between T1 and gate.
The first time I tried with software above, triac is broken, T1,t2 and gate's shorted.
And here is schematic of this led bulbs:
[url] https://drive.google.com/file/d/0Bz215_lkn4g-enBtMDVodUxCNUk/view?usp=sharing [/url] _________________ Begin Begin Begin !!! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|