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

INT_RDA causes strange pwm jiggling.
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
palyancodr



Joined: 06 Jan 2014
Posts: 31

View user's profile Send private message

INT_RDA causes strange pwm jiggling.
PostPosted: Mon Jan 06, 2014 8:08 pm     Reply with quote

Hi,

I am using ccs c ide version v4.110 programming 16f877a.

I generate single pwm signal using timer1 with 500us each interrupt no problem with that.

I added delay to make precise sets to high cycle of pwm, no problem with that either.

I need serial communication between two pics that's why I need an int_rda interrupt. The pic which generates pwm will read a value from the other one when the data is available or presents.

When i add int_rda to code, high cycle of the pwm jiggles and this jiggling effects the servo, I want rock solid pwm signal. Why do you think this jiggle happens?

I added a video link below belonging to virtual oscilloscope reading of that pwm. You can see the high duty jiggle as I zoom in through it.

Here is the link of the video: http://www.youtube.com/watch?v=lO2SNWzSeV8

Here is the code:
Code:
#include <16f877a.h>
#device ADC = 10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#use delay(clock = 20000000)
#use rs232 (baud = 9600, xmit = pin_c6, rcv = pin_c7, parity = N, stop = 1,ERRORS)

int16 preload = 63036;
int16 count = 0;
int16 serialCheck = 0;
int16 motorPwm = 0;
int16 sigThr = 0;


#int_timer1
void timer1_interrupt (){

set_timer1(preload + get_timer1());

count = count + 1;

}


#int_rda
void serial_interrupt(){         
                                 
   serialCheck = 1;             
   motorPwm = getc();         
   
   if(motorPwm != 0){
   
      sigThr = 4 * motorPwm;
   
   }

}


void main()
{

  setup_spi(SPI_SS_DISABLED);
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_comparator(NC_NC_NC_NC);
 
  SETUP_ADC_PORTS( NO_ANALOGS );
  SETUP_ADC(ADC_OFF);

  output_low(pin_d4);
  output_low(pin_d5);
  output_low(pin_d6);
  output_low(pin_d2);

  output_high(pin_d2);
  delay_ms(2000);
  output_low(pin_d2);
 
  enable_interrupts(INT_TIMER1);
  enable_interrupts(int_rda);
  enable_interrupts(GLOBAL);

  rs232_errors = 0;

for(;;){


   if (count == 37){
 
      output_high(pin_d5);

   }

       
   if(count == 39){
     
      delay_us(500);
      output_low(pin_d5);
      count = 0;
     
   }
}

}

_________________
Hardware-Software Developer
Physics Engineer
Ceo airVision Aerial Video and Photography
Ceo Massive Robotics

ccs c ide version: 4.110
Pic: 16F877
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jan 06, 2014 11:59 pm     Reply with quote

The "jiggle" is caused by the random delay injected by the #int_rda
interrupt. The CCS interrupt handler code takes time to execute, and
the user code inside your #int_rda routine also takes time. You can
count up the instruction cycles used to do this, by looking at the .LST
file. You can pretty much see where the jiggle comes from when you
do that.

Using the #priority statement won't fix this problem, because #int_rda
could already be in process when a Timer1 interrupt occurs.

Here is a possible fix:

Your Timer1 interrupt occurs every 500us. Your #int_rda interrupt
can occur every 1042us (at 9600 baud). So, you could remove the
separate #int_rda routine code and move it into the #int_timer1 routine.

You would now poll for the RDA interrupt inside the Timer1 routine and
then handle it there, if it occurs. You're polling it at a rate faster than
the RDA interrupt can occur, so it should work.

Handle the timer stuff first, inside the #int_timer1 routine. Then check for
the RDA interrupt. You will also have to clear the RDA interrupt flag if it's set.
Ttelmah



Joined: 11 Mar 2010
Posts: 19470

View user's profile Send private message

PostPosted: Tue Jan 07, 2014 1:46 am     Reply with quote

and remember that simply 'if (kbhit())' checks the RDA flag. Smile
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Jan 07, 2014 2:48 pm     Reply with quote

I assume you also understand,
that due to the way you create the "pwm" in PIC "SOFT" code,
making almost ANY change or addition in the structure of your
main() core loop - will also upset the output pattern as well.

If the timing of that "pwm" is critical, i would consider generating
it some other way.

For instance:

Using the PIC to control an 82C54 with a bit of added HCT logic to glue
2/3 of the chips' timers together comes quickly to mind.

Best of all - if using a crystal clock source-
the jitter will be amazingly small - not to mention consistent-
and you can get greater precision
in the duty cycle than coding for the pic by itself,
will ever provide.
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Jan 07, 2014 11:45 pm     Reply with quote

asmboy wrote:
I assume you also understand,
that due to the way you create the "pwm" in PIC "SOFT" code,
making almost ANY change or addition in the structure of your
main() core loop - will also upset the output pattern as well.

If the timing of that "pwm" is critical, i would consider generating
it some other way.

For instance:

Using the PIC to control an 82C54 with a bit of added HCT logic to glue
2/3 of the chips' timers together comes quickly to mind.

Best of all - if using a crystal clock source-
the jitter will be amazingly small - not to mention consistent-
and you can get greater precision
in the duty cycle than coding for the pic by itself,
will ever provide.


Or using a virtually pin compatible PIC18F4620 allowing you to use hardware high and low priority interrupts.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 11:06 am     Reply with quote

Code:
  setup_spi(SPI_SS_DISABLED);
This is invalid CCS Wizard generated code and could lead to undefined results. Please replace by:
Code:
  setup_spi(FALSE);
palyancodr



Joined: 06 Jan 2014
Posts: 31

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 7:34 pm     Reply with quote

Removing the int_rda interrupt and instead pulling it inside the timer1 or while loop was logical however tried it with the code below still no fix:S
Code:

#include <16f877a.h>
#device ADC = 10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#use delay(clock = 20000000)
#use rs232 (baud = 9600, xmit = pin_c6, rcv = pin_c7, parity = N, stop = 1,ERRORS,stream = PWMDIFF)

int16 preload = 63036;
int16 count = 0;
int16 serialCheck = 0;
int16 motorPwm = 0;
int16 sigThr = 0;


#int_timer1
void timer1_interrupt (){

set_timer1(preload + get_timer1());

count = count + 1;
}


void main()
{
  setup_spi(FALSE);
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_comparator(NC_NC_NC_NC);
 
  SETUP_ADC_PORTS( NO_ANALOGS );
  SETUP_ADC(ADC_OFF);

  output_low(pin_d4);
  output_low(pin_d5);
  output_low(pin_d6);
  output_low(pin_d2);

  output_high(pin_d2);
  delay_ms(2000);
  output_low(pin_d2);
 
  enable_interrupts(INT_TIMER1);
  enable_interrupts(GLOBAL);

  rs232_errors = 0;

for(;;){
   
   if(kbhit(PWMDIFF)){
   
      serialCheck = 1;             // 0 through pic pins.
      motorPwm = getc();         
   
      if(motorPwm != 0){
   
      sigThr = 4 * motorPwm;
   
      }
   
   }

   if (count == 37){
 
      output_high(pin_d5);
   }

       
   if(count == 39){
     
      delay_us(1000);
      output_low(pin_d5);
      count = 0;
   }
}

}

_________________
Hardware-Software Developer
Physics Engineer
Ceo airVision Aerial Video and Photography
Ceo Massive Robotics

ccs c ide version: 4.110
Pic: 16F877
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed Jan 08, 2014 8:23 pm     Reply with quote

IF the code you have now was to become functional JUST as you wish,
would it then be COMPLETE ??

meaning NO MORE code to be added ??

or is this a reduced example of part of some larger project ??

how low does the timing jitter have to be , for it to be considered
working properly ??
what is the allowable jitter time ?? how many usecs?

( i assume the design can already have at least several hundred nsecs - even when working "correctly" )


i can't say it more clearly than this:
the way you generate the ultimate output pulse train
is STRUCTURED too poorly to be trusted for real stability.

using that HUGE delay statement
just makes my head spin.


Last edited by asmboy on Wed Jan 08, 2014 8:27 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 8:25 pm     Reply with quote

Quote:
Removing the int_rda interrupt and instead pulling it inside the timer1 or while loop was logical however tried it with the code below still no fix


#int_timer1
void timer1_interrupt (){

set_timer1(preload + get_timer1());

count = count + 1;
}

You didn't do it. There is no RDA interrupt code inside #int_timer1.
palyancodr



Joined: 06 Jan 2014
Posts: 31

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 8:29 pm     Reply with quote

I tried both like this and like at the previous post. There is still jiggle.
Code:
#include <16f877a.h>
#device ADC = 10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#use delay(clock = 20000000)
#use rs232 (baud = 9600, xmit = pin_c6, rcv = pin_c7, parity = N, stop = 1,ERRORS,stream = PWMDIFF)

int16 preload = 63036;
int16 count = 0;
int16 serialCheck = 0;
int16 motorPwm = 0;
int16 sigThr = 0;


#int_timer1
void timer1_interrupt (){

set_timer1(preload + get_timer1());

count = count + 1;

   if(kbhit(PWMDIFF)){
   
      serialCheck = 1;             // 0 through pic pins.
      motorPwm = getc();         
   
      if(motorPwm != 0){
   
      sigThr = 4 * motorPwm;
   
      }
   
   }
}


void main()
{
  setup_spi(FALSE);
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_comparator(NC_NC_NC_NC);
 
  SETUP_ADC_PORTS( NO_ANALOGS );
  SETUP_ADC(ADC_OFF);

  output_low(pin_d4);
  output_low(pin_d5);
  output_low(pin_d6);
  output_low(pin_d2);

  output_high(pin_d2);
  delay_ms(2000);
  output_low(pin_d2);
 
  enable_interrupts(INT_TIMER1);
  enable_interrupts(GLOBAL);

  rs232_errors = 0;

for(;;){
   

   if (count == 37){
 
      output_high(pin_d5);
   }

       
   if(count == 39){
     
      delay_us(1000);
      output_low(pin_d5);
      count = 0;
   }
}

}

_________________
Hardware-Software Developer
Physics Engineer
Ceo airVision Aerial Video and Photography
Ceo Massive Robotics

ccs c ide version: 4.110
Pic: 16F877
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 8:59 pm     Reply with quote

Quote:
I tried both like this and like at the previous post. There is still jiggle.

I didn't see it. I tested your original program and your latest program
with vs. 5.016. With the original program, if I open a TeraTerm window
and hold down any key so it auto-repeats, I definitely see a jiggle of at
least 10us on the falling edge of the PWM signal. If I install your latest
posted program and run it, I do not see any jiggle.

Also, I said in my previous post that if you get the RDA interrupt, then
you need to clear it. I have added a line to do this as shown below:
Code:

#int_timer1
void timer1_interrupt (){

set_timer1(preload + get_timer1());

count = count + 1;

   if(kbhit(PWMDIFF)){
   
      serialCheck = 1;             // 0 through pic pins.
      motorPwm = getc();         
   
      if(motorPwm != 0){
   
      sigThr = 4 * motorPwm;
      }
    clear_interrupt(INT_RDA);   // *** CLEAR THE INTERRUPT ***
   }
}
palyancodr



Joined: 06 Jan 2014
Posts: 31

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 9:09 pm     Reply with quote

With your correction at your latest post, i still have jiggle around 10us. Your suggestion must have solved the problem,however; mine is still have jiggle. Do you think that this can occur because of my ccs version 4.110?
_________________
Hardware-Software Developer
Physics Engineer
Ceo airVision Aerial Video and Photography
Ceo Massive Robotics

ccs c ide version: 4.110
Pic: 16F877
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 11:05 pm     Reply with quote

I installed vs. 4.110 and I see a little bit of jiggle. Maybe 4us at most.
So I re-installed vs. 5.016 and I am seeing it there too. I think it's
because you update your PWM pin outside of the #int_timer1 routine.

Normally, software PWM will do the pin update inside the interrupt routine.
If I move the code that's inside the for(;;) loop, so it's inside the
#int_timer1 routine, then I don't even see the 4us of jiggle. It's stable.
palyancodr



Joined: 06 Jan 2014
Posts: 31

View user's profile Send private message

PostPosted: Wed Jan 08, 2014 11:21 pm     Reply with quote

Here is the latest version of code that i am having problem with if some you having the same problem, thanks to PCM programmer, the code is jiggle free. Thanks for helping me out PCM programmer and all of the fellas posting suggestions here.
Code:

#include <16f877a.h>
#device ADC = 10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#use delay(clock = 20000000)
#use rs232 (baud = 9600, xmit = pin_c6, rcv = pin_c7, parity = N, stop = 1,ERRORS,stream = PWMDIFF)

int16 preload = 63036;
int16 count = 0;
int16 serialCheck = 0;
int16 motorPwm = 0;
int16 sigThr = 0;


#int_timer1
void timer1_interrupt (){

set_timer1(preload + get_timer1());

count = count + 1;

   if(kbhit(PWMDIFF)){
   
      serialCheck = 1;             
      motorPwm = getc();         
   
      if(motorPwm != 0){
   
      sigThr = 4 * motorPwm;
   
      }
           
      clear_interrupts(int_rda);     

   }

   if (count == 37){
 
      output_high(pin_d5);
   }

       
   if(count == 39){
     
      delay_us(1000);
      output_low(pin_d5);
      count = 0;
   }
}

}


void main()
{
  setup_spi(FALSE);
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_comparator(NC_NC_NC_NC);
 
  SETUP_ADC_PORTS( NO_ANALOGS );
  SETUP_ADC(ADC_OFF);

  output_low(pin_d4);
  output_low(pin_d5);
  output_low(pin_d6);
  output_low(pin_d2);

  output_high(pin_d2);
  delay_ms(2000);
  output_low(pin_d2);
 
  enable_interrupts(INT_TIMER1);
  enable_interrupts(GLOBAL);

  rs232_errors = 0;

for(;;){
   



}

_________________
Hardware-Software Developer
Physics Engineer
Ceo airVision Aerial Video and Photography
Ceo Massive Robotics

ccs c ide version: 4.110
Pic: 16F877
Ttelmah



Joined: 11 Mar 2010
Posts: 19470

View user's profile Send private message

PostPosted: Thu Jan 09, 2014 2:01 am     Reply with quote

Your serial check should be after the PWM. Otherwise there will be a few uSec of jiggle (tiny, but still there).
Note PCM_programmers comment:

"Handle the timer stuff first, inside the #int_timer1 routine. Then check for
the RDA interrupt. You will also have to clear the RDA interrupt flag if it's set."

Note the 'then'.

Best Wishes
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 1, 2  Next
Page 1 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