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

square wave code

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



Joined: 22 Jan 2012
Posts: 3
Location: UK

View user's profile Send private message

square wave code
PostPosted: Sun Jan 22, 2012 3:21 am     Reply with quote

Hi everyone. I am learning Pic and C programming. I'm trying to generate a squarewave (ac) output of period 20ms using full bridge pwm. However, I'm getting a square wave sometimes and then at times the PIC seems to lockup with an undefined output more like a modified sine wave. Can someone please give me some direction. The code is attached.
Code:

#include "16f690.h"
#device adc=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PUT                      //Power Up Timer ON
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOBROWNOUT               //No brownout reset
#FUSES IESO                     //Internal switch over mode ON
#FUSES FCMEN                    //Fail safe clock monitor enabled
#FUSES NOCPD                    //No code protection from EE
#FUSES NOPROTECT                //No code read protection

#use delay(internal=31kHz)

void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED); 
setup_timer_2(T2_DIV_BY_1,22, 1); //prescaler and post scaler set>> 1
setup_ccp1(CCP_PWM | CCP_PWM_FULL_BRIDGE | CCP_PWM_H_H | CCP_SHUTDOWN_AC_L | CCP_SHUTDOWN_BD_L);  //set shutdown mode         
set_pwm1_duty(700);               // duty cycle
setup_comparator(NC_NC_NC_NC);             //not used>> no comparator.
setup_oscillator(OSC_31KHZ);

while(TRUE)
  {
   // Positive half cycle.
   setup_ccp1(CCP_PWM_FULL_BRIDGE | CCP_PWM_H_H);
   set_pwm1_duty(700);
   delay_ms(1);       //delay to avoid both forward and reverse at same time
 
   // Negative half cycle.
   setup_ccp1(CCP_PWM_FULL_BRIDGE_REV  | CCP_PWM_H_H);
   set_pwm1_duty(700);
   delay_ms(1);          //delay to avoid reverse and forward at same time
  }

}

_________________
'He who riseth late shall trot all day'
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Sun Jan 22, 2012 5:31 am     Reply with quote

Comments inline:
Code:

#include "16f690.h"
#device adc=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PUT                      //Power Up Timer ON
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOBROWNOUT               //No brownout reset
#FUSES IESO                     //Internal switch over mode ON
#FUSES FCMEN                    //Fail safe clock monitor enabled
#FUSES NOCPD                    //No code protection from EE
#FUSES NOPROTECT                //No code read protection

#use delay(internal=31kHz)

void main(void) {
   setup_adc_ports(NO_ANALOGS); //don't set a voltage range
   setup_adc(ADC_OFF);
   setup_spi(FALSE); //Error in the wizard - FALSE turns the SPI off
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); //Are you using this?.
   //Disable if not.
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,22, 1); //prescaler and post scaler set>> 1
   //Frequency = 31000/(4*23)Hz = 337Hz - Not what you describe
   setup_ccp1(CCP_PWM | CCP_PWM_FULL_BRIDGE | CCP_PWM_H_H |  CCP_SHUTDOWN_AC_L | CCP_SHUTDOWN_BD_L);  //set shutdown
mode
   //Are you using shutdown inputs ?. If not this could result in random
   //shutdown of the PWM.....         
   set_pwm1_duty(700);               // duty cycle
   //Big problem here - max duty cycle is (Timer2 max count+1)*4
   //All that will happen is this will lock the PWM 'on' permanently....
   //Same applies with the same value below - changing it again does
   //nothing, the value is stored unless changed...
   
   setup_comparator(NC_NC_NC_NC);             //not used>> no comparator.
   setup_oscillator(OSC_31KHZ); //Not needed

   while(TRUE) {
      // Positive half cycle.
      setup_ccp1(CCP_PWM_FULL_BRIDGE | CCP_PWM_H_H);
      set_pwm1_duty(700);
      delay_ms(1);       //delay to avoid both forward and reverse at same time
 
      // Negative half cycle.
      setup_ccp1(CCP_PWM_FULL_BRIDGE_REV  | CCP_PWM_H_H);
      set_pwm1_duty(700);
      delay_ms(1);          //delay to avoid reverse and forward at same time
   }
}


As it stands, you are not using the PWM at all. Just loading a value larger than it'll accept into the timing register, so the output is locked on, and reversing using the loop.....
The intermittent behaviour may well be because the shutdown inputs are floating.
Also as a further comment, if you had a PWM running at 50Hz (20mSec), how can you reverse this every 1000th second.....

Best Wishes
malaika7



Joined: 22 Jan 2012
Posts: 3
Location: UK

View user's profile Send private message

square wave code
PostPosted: Sun Jan 22, 2012 6:24 am     Reply with quote

Thank you for your response but I'm sorry I don't understand. I'm only beginning playing with these things. I have setup PWM and yet you say I'm not using it. I have tried a count of 154 but no luck. I tried a delay of 10ms per half cycle to give me a total of 20ms but the period extended even further. However, your explanation of duty cycle and frequency is eye opening. Thanks loads. Suppose I remove the delay, would that be safe? Please advise.
_________________
'He who riseth late shall trot all day'
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Sun Jan 22, 2012 8:51 am     Reply with quote

Have a look at the data sheet. Page 131. Particularly the 'note' above the table. This is what you are doing.
Just to show the PWM running, try:
Code:

   //Obviously in a 'main' as for your code
   setup_timer_2(T2_DIV_BY_1,154, 1);
   //Frequency = 31000/(4*155)Hz = 50Hz
   setup_ccp1(CCP_PWM | CCP_PWM_FULL_BRIDGE | CCP_PWM_H_H);
   set_pwm1_duty(308L);
   do {
       delay_ms(1000);
       setup_ccp1(CCP_PWM_FULL_BRIDGE_REV  | CCP_PWM_H_H);
       delay_ms(1000);
       setup_ccp1(CCP_PWM_FULL_BRIDGE | CCP_PWM_H_H);
   } while; //Just sit letting the PWM run on it's own, reversing every second.


Best Wishes
malaika7



Joined: 22 Jan 2012
Posts: 3
Location: UK

View user's profile Send private message

square wave code
PostPosted: Sun Jan 22, 2012 11:06 am     Reply with quote

I think I understand this one . The duty 308L however bits me. I thought duty would be between 1 and (154+1)*4. I know L stands for 'long' but what does it mean here? Does the 50Hz translate onto my square wave output or is it just the modulation frequency?
Once more thank you so much.
_________________
'He who riseth late shall trot all day'
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Sun Jan 22, 2012 3:45 pm     Reply with quote

The 'L' forces a constant to be treated as a 'long'.
Now with '308', it actually does nothing, _but_ when you "tried 154", it'd make a huge difference. If you read the manual for the set_pwm_duty function, it has two different modes of operation. If you call it with a 'long' value, the value is placed into the ten bits of the full PWM duty cycle register. However if you call it with a 'short' value, the number is put into just the top eight bits of the PWM duty cycle (quicker). Problem is that this means that the behaviour will change when a value goes below 256, unless you _explicitly_ tell the code to treat the vale as a 'long'. So when you tried 154, this (since it was > 256), it was treated as an 8bit value, and put into the upper 8 bits of the ten bit register (effectively multiplied by 4), so gave the same behaviour as 616!.....
Hence it is good practice when putting a constant into the PWM function, to be _explicit_, and tell the compiler to treat it as long, no matter what the value involved.
A search on the PWM here will find a lot of threads explaining this/

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