|
|
View previous topic :: View next topic |
Author |
Message |
Spradecom
Joined: 01 Jun 2011 Posts: 19 Location: INDIA
|
Problem in PWM dimming |
Posted: Thu Nov 01, 2012 1:59 am |
|
|
Hi, I had tried to write program for pulse reading and generate PWM according to input pulse width. AC triac dimmer used. Optocoupler gives square wave input with variable pulse width. I am facing problem of flickering at minimum level at minimum level PWM pulse width varies, so output get disturb. I had tried to solve but same problem can't solve. I am attaching circuit for following. Please guide me how to avoid flicker problem. Also my code as following
[img] TRiac_dimmer[/img]
Code: |
signed int16 i;
signed int16 old_time;
#int_TIMER0
void TIMER0_isr(void)
{
ir_data_counter ++;
if(remote_time_out_counter < 156)
{
remote_time_out_counter ++;
}
else
{
remote_time_out_counter = 0;
ir_pulse_counter = 0;
remote_data = 0;
}
if(remote_key_release_counter < 400)
{
remote_key_release_counter ++;
}
else
{
remote_key_release_counter = 0;
remote_key_released = 1;
}
if(!ready_for_delay_off)
{
if(led_delay_counte < 400)
{
led_delay_counte ++;
STATUS_LED = 0;
}
else
{
STATUS_LED = 1;
}
}
if(pulse width != temp_pulse width)
{
if(ramp_delay_counter < 10)
{
ramp_delay_counter ++;
}
else
{
if(pulse width < temp_pulse width)
{
pulse width ++;
}
else if(pulse width > temp_pulsewidth)
{
pulsewidth --;
}
ramp_delay_counter = 0;
}
set_pwm1_duty(pulsewidth);
}
if(start_time)
{
if(save_time_counter < FIVE_SECOND)
{
save_time_counter ++;
save_data = 0;
}
else
{
save_time_counter = 0;
save_data = 1;
start_time = 0;
}
}
}
void main()
{
setup_adc_ports(sAN5|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
// setup_timer_1(T1_DISABLED);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_4,124,2);
// setup_timer_2(T2_DIV_BY_16,249,1);
// setup_timer_2(T2_DIV_BY_16,249,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
ext_int_edge(H_TO_L);
// enable_interrupts(INT_EXT);
// enable_interrupts(INT_TIMER0);
setup_oscillator(OSC_4MHZ);
initialise_ports();
initialise_variables();
set_adc_channel(5);
delay_ms(100);
recall_eeprom();
// read_pot_position();
// enable_interrupts(GLOBAL);
old_time = 0 ;
while(TRUE)
{
//wait_for_low_to_high();
//set_timer1(0);
//wait_for_low();
// time = get_timer1();
//-----------------------------------------
// Timer setting and calculation.
// Make timer1 as 16 bit from 0 - FFFF
// Our PWM is 0-1023
// Resolution at 4MHZ internal frequency = 1us
//Internal clock divided by 1
// while(input(PIN_A2)); // External input pin =1
// set_timer1(0); // set our timer to zero.
// while(!input(PIN_A2));
// time = get_timer1();
// big_time= 0;
// for(i = 0; i < 1000; i ++)
{
// big_time += get_timer1();
}
// time = big_time/ i;
// time= time/10 ;
big_time = 0 ; // initial value set to zero
for(i = 0; i < 100; i ++)
{
big_time+=get_pulse_time(); // accumulation
}
time1 = big_time / i;
/*------------------------------------------------
once we get the calulated time, now make the pwm work
according to our square wave input.
-----------------------------------------------------------*/
// if(time1<=460)
// for(i= 0; i<300 ; i++)
// {
// big_time+=get_pulse_time(); // accumulation
// }
if(time1<=245)
//if(time1<=400)
{
// for(i= 0; i<150 ; i++)
// {
// big_time+=get_pulse_time(); // accumulation
// }
time1 = 3;
// set_pwm1_duty(time1);
}
else if(time1>245 && time1<= 265)
{
time1= 12 ;
}
else if(time>=830)
{
time1 = 1000 ;
}
else
{
// time1 = (time1-400)*1.7 ;
time1 = (time1-245)*1.7 ;
// time = (time-300)*1.85 ;
time1 = time1 /2;
//set_pwm1_duty(time1);
}
/// set_pwm1_duty(time1);
while(old_time!= time1)
{
if(ramp_delay_counter < 3 )
{
ramp_delay_counter ++;
}
else
{
if(old_time<time1)
{
old_time = old_time + 1;
delay_ms(1);
set_pwm1_duty(old_time);
delay_ms(2);
}
else if(old_time> time1)
{
old_time = old_time - 1;
delay_ms(1);
set_pwm1_duty(old_time);
delay_ms(2);
}
ramp_delay_counter = 0;
//if(((time1 - 2) > old_time) || ((time1 + 2) < old_time))
// {
// old_time =time1;
// set_pwm1_duty(old_time);
// }
}
//if(old_time<time1)
// {
// old_time++;
// set_pwm1_duty(old_time);
}
//delay_ms(5000);
}
}
void initialise_ports(void)
{
output_float(PIN_A0);
output_float(PIN_A1);
output_float(PIN_A2);
output_float(PIN_A3);
output_low(PIN_A4);
output_float(PIN_A5);
output_float(PIN_C0);
output_float(PIN_C1);
output_float(PIN_C2);
output_float(PIN_C3);
output_float(PIN_C4);
output_low(PIN_A5);
IR_SENSOR = 1;
}
void initialise_variables(void)
{
ir_pulse_counter = 0;
ir_data_counter = 0;
remote_data = 0;
last_remote_data = 0;
ready_for_delay_off = 0;
data_changed = 0;
power_on = 1;
last_adc_data_loaded = 0;
last_adc_data = 0;
using_remote = 1;
remote_key_release_counter = 0;
remote_key_released = 1;
led_delay_counte = 0;
led_on_for_delay = 0;
pulsewidth = 0;
temp_pulsewidth = 0;
save_time_counter = 0;
start_time = 0;
save_data = 0;
}
void read_manual_setting(void)
{
signed int32 adc_data;
unsigned int16 i;
signed int16 temp;
set_adc_channel(5);
adc_data = 0;
for(i = 0; i < 1250; i ++)
{
adc_data += read_adc(ADC_START_AND_READ);
}
temp = adc_data / i;
if(((temp - 2) > last_minium_adc_data) || ((temp + 2) < last_minium_adc_data))
{
last_minium_adc_data = temp;
if(temp < 10)
{
temp = 0;
}
if(using_remote)
{
if(((temp - 50) > last_adc_data) || ((temp + 50) < last_adc_data))
{
using_remote = 0;
last_adc_data = temp;
temp_pulsewidth = temp;
data_changed = 1;
}
}
else
{
temp_pulsewidth = temp;
data_changed = 1;
if(((temp - 5) > last_adc_data) || ((temp + 5) < last_adc_data))
{
last_adc_data = temp;
// save_last_data();
save_time_counter = 0;
save_data = 0;
start_time = 1;
}
}
}
}
void my_delay_ms(unsigned int16 ms_delay)
{
unsigned int16 counter;
while(ms_delay--)
{
for(counter = 0; counter < 40; counter ++);
}
}
void wait_for_low_to_high(void) {
while(input(PIN_A2)) ; /* if it's high, wait for a low */
delay_us(3); /* account for fall time */
while(!input(PIN_A2)); /* wait for signal to go high */
}
void wait_for_low(void) {
delay_us(3); /* account for rise time */
while(input(PIN_A2)); /* wait for signal to go low */
}
signed int16 get_pulse_time(void)
{
while(input(PIN_A2)); // External input pin =1
set_timer1(0); // set our timer to zero.
while(!input(PIN_A2));
time = get_timer1();
time = time/10 ;
time = 1000-time;
return time ;
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Nov 01, 2012 5:57 am |
|
|
You need to understand something about TRIAC's. Basically once turned 'on' they can't go off again, till the next zero crossing point on the mains cycle. So if you control a TRIAC circuit with a PWM that is not syncronised to the main, you _will_ get flicker. Nothing you can do about this in code. What happens is you PWM goes off, and up to 1/100th second later (in the UK), or 1/120th second later (in the US), the actual circuit goes off. Since the clocks are not in sync, the delay will vary from 0 to the times given, as the clocks beat together. Result flicker. The amount will be tiny at high power, but get worse the lower the power level.
Only solutions are in hardware. You need somehow to detect the mains zero crossing, and synchronise your PWM to this.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Nov 01, 2012 10:09 am |
|
|
I can't see your circuit, or a link to it on the post.
This topic has been discussed recently on the forum, do a search.
Mike |
|
|
|
|
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
|