CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Problem in PWM dimming

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Spradecom



Joined: 01 Jun 2011
Posts: 19
Location: INDIA

View user's profile Send private message MSN Messenger

Problem in PWM dimming
PostPosted: Thu Nov 01, 2012 1:59 am     Reply with quote

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: 19347

View user's profile Send private message

PostPosted: Thu Nov 01, 2012 5:57 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Nov 01, 2012 10:09 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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