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 CCS Technical Support

ADC and PWM Problem
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Mon Jun 28, 2010 4:05 am     Reply with quote

Here is the code part that makes the blink problem.

The main idea is; to read from adc, generate PWM with appropiate duty, then to read adc again. It continues forever. If adc value is 255 i stop pwm and give high to one of the port E pins. If 0, i stop pwm.

Code:

if (led_res>=255) { //value of ADC
            //.... :arrow: here is the part which drives led without PWM from pins   E1&E2
       }
       else {  // this part is driving with PWM
            output_low(pin_e2);  // are those again affect tris values  :question:
            output_low(pin_e1); 
            if (BK=='B') {  //if first led is chosen
               setup_ccp1(CCP_PWM);
               set_pwm1_duty(led_res);
               //Delay_ms(100);
            }
            else { // if second led is chosen
                 setup_ccp2(CCP_PWM);
                 set_pwm2_duty(led_res);
                 //Delay_ms(100);
            }
       }


output_low(pin_e2); -> What can i write instead of this to clear that pin Question To be honest im confused with that thing. I wrote numerious codes and used both assemly and C compilers but i have never heard that kind of a thing. Is there a problem with CCS ? Is changing port situation mixing up with tris in CCS ? Because normally it shouldn't happen.
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Mon Jun 28, 2010 4:32 am     Reply with quote

Also i should say that i see that blinking or flickering problem obviously when there is no delay. If i put a delay, i see that problem rarely but i see it.

One more thing; whatever i do, this problem occurs more obvious when PWM duty is really low. When its high u should look carefully to see it but it still does Sad
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Mon Jun 28, 2010 6:28 am     Reply with quote

I uploaded a video from oscilloscope Smile
http://rapidshare.com/files/403524343/MOV00007.3gp.html

The waveform you see is from pic output (one of the CCP modules). My camera is not so qualified for this thing. You will see the duty is changing according to adc value. When the value is close to 0, the change is max. (like 10us) But when I'm close to 255 i see its shorter than 10us. If you look carefully you will see that it really happens till i turn off the supply.

What kind of a thing may cause this problem ? Any idea ?
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Mon Jun 28, 2010 6:37 am     Reply with quote

CCS_Kid wrote:
Here is the code part that makes the blink problem.

The main idea is; to read from adc, generate PWM with appropiate duty, then to read adc again. It continues forever. If adc value is 255 i stop pwm and give high to one of the port E pins. If 0, i stop pwm.

Code:

if (led_res>=255) { //value of ADC
            //.... :arrow: here is the part which drives led without PWM from pins   E1&E2
       }
       else {  // this part is driving with PWM
            output_low(pin_e2);  // are those again affect tris values  :question:
            output_low(pin_e1); 
            if (BK=='B') {  //if first led is chosen
               setup_ccp1(CCP_PWM);
               set_pwm1_duty(led_res);
               //Delay_ms(100);
            }
            else { // if second led is chosen
                 setup_ccp2(CCP_PWM);
                 set_pwm2_duty(led_res);
                 //Delay_ms(100);
            }
       }


output_low(pin_e2); -> What can i write instead of this to clear that pin Question To be honest im confused with that thing. I wrote numerious codes and used both assemly and C compilers but i have never heard that kind of a thing. Is there a problem with CCS ? Is changing port situation mixing up with tris in CCS ? Because normally it shouldn't happen.


You declared Led_res as type long. This means the compiler will use 10 bit pwm mode instead of 8 bits. What this means is that the duty cycle that you will get is actually 1/4 lower than what you intend.
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Mon Jun 28, 2010 7:25 am     Reply with quote

mkuang wrote:

You declared Led_res as type long. This means the compiler will use 10 bit pwm mode instead of 8 bits. What this means is that the duty cycle that you will get is actually 1/4 lower than what you intend.


Should i declare it unsigned ?
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Mon Jun 28, 2010 7:32 am     Reply with quote

CCS_Kid wrote:
mkuang wrote:

You declared Led_res as type long. This means the compiler will use 10 bit pwm mode instead of 8 bits. What this means is that the duty cycle that you will get is actually 1/4 lower than what you intend.


Should i declare it unsigned ?


Try declaring it as int8.

CCS assumes it is unsigned unless you specifically tells it that it is signed.
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Mon Jun 28, 2010 2:43 pm     Reply with quote

I did but duty is not linearly increase :( When i declare as long then there is linearity
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Mon Jun 28, 2010 3:18 pm     Reply with quote

Post the program that you used to test, with the fuses and the timer2 settings. Timer2 is important since that is the one used for hardware pwm.
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

Adding İnterrupt :(
PostPosted: Fri Jul 09, 2010 1:15 am     Reply with quote

ADC and PWM works now. Thanks for your help. I've changed my adc and pwm to 10bit. Also changed the code little bit and its ok now.

But I have another problem. I add interrupt to my code and when I power on it goes into the interrupt routine and stays there. It doesn't come back to the main code. Why is this happening ?

Also if somehow it returns to the main program, it gets stuck in interrupt routine when the pwm duty is %50. It doesn't make any sense.

I've checked the hardware but there is no signal change on those pins. Its some kind of a software problem.

Note: I'll attach the code soon.
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Fri Jul 09, 2010 1:57 am     Reply with quote

Code:

  #include <float.h>
  #include <stdio.h>
  #include <stdlib.h>
 
char BK,yedek;
long led_res,old_led_res,led_res_iki,i;
int8 value;
unsigned flag_PWM_stop,okuma_b,timer_bayrak;
 
#int_RB
void  RB_isr(void)
{
output_high(pin_c3);
delay_ms(500);
output_low(pin_c3);
delay_ms(500);
}

#int_EXT
void  EXT_isr(void)
{
    disable_interrupts(INT_EXT);
    disable_interrupts(GLOBAL);
    clear_interrupt(INT_EXT); 
}

void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_8);
   set_adc_channel(0);
   setup_timer_2(T2_DIV_BY_16,254,1);
   
   set_tris_b(0xFF);
   //output_b(0x00);
   ext_int_edge(L_to_H);
   enable_interrupts(INT_RB);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   set_pwm1_duty(0L);   
   set_pwm2_duty(0L);
   
   yedek='L',BK='L';
   
   value=0;
   timer_bayrak=0;

   //TODO: User Code
   
anadongu:

   do { 
     
   switch_control:
       if (input(pin_c5)){         
          BK='B';
          setup_ccp2(CCP_OFF);
          enable_interrupts(INT_RB);
          enable_interrupts(INT_EXT);
          enable_interrupts(GLOBAL);
       }
       else if (input(pin_C4)) {   
            BK='K';
            setup_ccp1(CCP_OFF);
            enable_interrupts(INT_RB);
            enable_interrupts(INT_EXT);
            enable_interrupts(GLOBAL);
       }
       else {
            setup_ccp1(CCP_OFF);
            setup_ccp2(CCP_OFF);
            output_low(pin_e2);
            output_low(pin_e1);
            output_low(pin_c3);
            disable_interrupts(INT_EXT);
            disable_interrupts(INT_RB);
            disable_interrupts(GLOBAL);
            clear_interrupt(INT_EXT);
            goto switch_control;
       }
       
       led_res = read_adc();
       if (led_res<=25) {
         led_res=25;
         old_led_res=led_res;
       }
       output_D(led_res);
       led_res_iki=led_res>>8;
       old_led_res = led_res;
       
       if (led_res>=1020) {           
          led_res=1023;
          if (input(pin_C5)) {
             output_high(pin_e2);                                               
             setup_ccp1(CCP_PWM);
             set_pwm1_duty(1023L);
             setup_ccp2(CCP_OFF);
             setup_timer_2(T2_DISABLED,254,1);
             timer_bayrak=1;
             value=get_timer2();
          }
          else if (input(pin_C4)) {
               output_high(pin_e1);             
               setup_ccp2(CCP_PWM);
               set_pwm2_duty(1023L);
               setup_ccp1(CCP_OFF);
               setup_timer_2(T2_DISABLED,254,1);
               timer_bayrak=1;
               value=get_timer2();
          }
          else {
               set_pwm2_duty(0L);
               set_pwm2_duty(0L);
               output_low(pin_e2);
               output_low(pin_e1);
          }
       }
       else if(led_res<=25) {
            led_res=25L;
            old_led_res=led_res;
            output_low(pin_e2);
            output_low(pin_e1);
            if (BK=='B') {
               if (timer_bayrak==1) {
                 set_timer2(value);
                 setup_timer_2(T2_DIV_BY_16,254,1);
                 timer_bayrak=0;
               }
               setup_ccp1(CCP_PWM);
               set_pwm1_duty(25L);
            }
            else {
                 if (timer_bayrak==1) {
                    set_timer2(value);
                    setup_timer_2(T2_DIV_BY_16,254,1);
                    timer_bayrak=0;
                 }
                 setup_ccp2(CCP_PWM);
                 set_pwm2_duty(25L);
            }
       }
       else {       
            if (BK=='B') {
               if (timer_bayrak==1) {
                  set_timer2(value);
                  setup_timer_2(T2_DIV_BY_16,254,1);
                  timer_bayrak=0;
               }
               setup_ccp1(CCP_PWM);
               set_pwm1_duty(led_res);
            }
            else {
                  if (timer_bayrak==1) {
                     set_timer2(value);
                     setup_timer_2(T2_DIV_BY_16,254,1);
                     timer_bayrak=0;
                  }
                  setup_ccp2(CCP_PWM);
                  set_pwm2_duty(led_res);
            }
            output_low(pin_e2);
            output_low(pin_e1);
       }
   }while(1);
}


Hope u can help me
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Jul 09, 2010 2:23 am     Reply with quote

You don't need to disable or clear INT_EXT, in the INT_EXT handler.

Your problem though is INT_RB. INT_RB, reflects a hardware 'event', that there is a character waiting in the serial buffer. It will _continuously_ trigger, untill this hardware event is stopped (read the character). You _must_ handle the hardware event.
Get rid of the delays in the interrupt as well. These _will_ potentially lead to other problems. Make sure you have 'ERRORS' in your RS232 setup (which you don't show), otherwise these will almost certainly result in the hardware UART being completely hung.

Best Wishes
CCS_Kid



Joined: 22 Jun 2010
Posts: 17

View user's profile Send private message

PostPosted: Fri Jul 09, 2010 5:38 am     Reply with quote

Ttelmah wrote:

Your problem though is INT_RB. INT_RB, reflects a hardware 'event', that there is a character waiting in the serial buffer. It will _continuously_ trigger, untill this hardware event is stopped (read the character). You _must_ handle the hardware event.


How can I handle it ?

Note : I wrote delay lines to see if its still in interrupt. I don't need them and I deleted those lines.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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