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

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



Joined: 08 Sep 2003
Posts: 6

View user's profile Send private message

pgen
PostPosted: Wed Jul 28, 2004 12:53 pm     Reply with quote

I am struggling to use the pwm for frequencies under 100hz. By reading the description of the example I see there is a new example ex_pgen.c that may do what I want. Can someone supply me with the example.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 29, 2004 12:38 pm     Reply with quote

Quote:
I am struggling to use the pwm for frequencies under 100Hz.

Look near the end of this thread. Ttelmah and Mark have posted
a routine for software PWM which uses the RTCC (also called Timer0).
http://www.ccsinfo.com/forum/viewtopic.php?t=17993&highlight=pwm
They didn't show the setup code for the RTCC, so I've taken the liberty
of making a test program. For a PIC with a 4 MHz crystal, this demo
program creates a PWM signal on Pin B1, with a frequency of 100 Hz,
and a 25% duty cycle.

Code:
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)

#define PWM_PIN  PIN_B1

#define LOOPCNT 39

int8 width;

//-------------------------------
#INT_RTCC
void tick_interrupt(void);

//====================================
main()
{
width = 10;

setup_counters(RTCC_INTERNAL, RTCC_DIV_1);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
 
while(1);
}

//====================================
#INT_RTCC
void tick_interrupt(void)
{
static int8 loop = LOOPCNT;
static int8 pulse;

if(--loop == 0)
  {
   loop = LOOPCNT;
   pulse = width;
  }

if(pulse)
  {
   output_high(PWM_PIN);
   pulse--;
  }
else
  {
   output_low(PWM_PIN);
  }

}


Remember, this is for low frequency PWM, which requires a software
method. For higher frequencies, you can use the built-in hardware
PWM module which is present on many PICs. CCS has an example
of hardware PWM in their example file, EX_PWM.C.
andys



Joined: 23 Oct 2006
Posts: 175

View user's profile Send private message

pgen
PostPosted: Thu Jan 25, 2007 6:48 pm     Reply with quote

What is LOOPCNT?
and int8 is taken from header file and is
#define BYTE int???
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Thu Jan 25, 2007 9:16 pm     Reply with quote

Did you look at the other post? It is a #define which equates to 30. int8 is a CCS variable type, 8 bit integer.
umka



Joined: 28 Aug 2007
Posts: 99
Location: New Zealand

View user's profile Send private message

PostPosted: Sat Apr 19, 2008 4:04 am     Reply with quote

I am trying to implement this PWM but am having problems compiling. when i compile with the code below it gives errors:
Error 51 a numeric expression must appear here
Error 12 unidentified identifier pulse
Error 12 unidentified identifier pulse
Error 12 unidentified identifier pulse
Error 51 a numeric expression must appear here
Code:
  #INT_RTCC
void tick_interrupt(void)
{
static int8 loop = LOOPCNT;
static int8 pulse;

if(--loop == 0)
  {
   loop = LOOPCNT;
   pulse = width;
  }

if(pulse)
  {
   output_high(PWM_PIN);
   pulse--;
  }
else
  {
   output_low(PWM_PIN);
  }

}

so i have changed the code to below
Code:
#INT_RTCC
void tick_interrupt(void)
   {
      static int8 loop, pulse;
     
      loop = LOOPCNT;   // if width=loopcnt then duty=100%
     
         if (--loop == 0)
         {
            loop = LOOPCNT;
            pulse = PWM_Width;
         }
         if (pulse)
         {
            output_high(PWM_Pin);
            --pulse;
         }
      else output_low(PWM_Pin);
   }

Is the code the same? i think it is but just want confirmation. also how does the if (pulse) statement work?
Ttelmah
Guest







PostPosted: Sat Apr 19, 2008 4:48 am     Reply with quote

Major change.
The original, only initialised 'loop', _the first time the routine is called_, and resets it, only when loop == 0. The new code, re-initialises it _every time through the loop_. This prevents loop from actually counting on successive calls, and will stop it working....
The original as posted will compile. I'd suggest that you actually have a fault a few lines earlier in the code, which is preventing 'pulse' from being defined properly.

Best Wishes
umka



Joined: 28 Aug 2007
Posts: 99
Location: New Zealand

View user's profile Send private message

PostPosted: Sat Apr 19, 2008 4:53 am     Reply with quote

Here is my complete code. It is unfinished hence some stuff missing or not making sense. it will receive a speed reference for a PID motor controller over the rs232. trying to compile this but i get the errors. Compiler is pcwh 4.038

Code:
#include <16F628a.h>
#device icd=true
#fuses HS,NOLVP,NOWDT
#use delay(clock=4000000)
#use rs232(baud=19200, xmit=PIN_B2, rcv=PIN_B1, ERRORS, LONG_DATA)

#define PWM_Pin   Pin_B5
#define Wait_LED  Pin_A0
#define Run_LED   Pin_A1
#define LOOPCNT   (30);    // define PWM period for approx 50Hz

int16 Speed_Value;         // Long value recieved over serial comm
int16 Speed_Reference;     // Long value used in main routine
int8 PWM_Width;            // PWM pulse width
int1 SI_Flag;              // Serial interupt flag
int1 CCP1_Flag;            // Speed update

#INT_RDA
void serial_isr()          // Get serial data
   {
      Speed_Value = getc();
         SI_Flag == 1;
   } 

#INT_RTCC
   void tick_interrupt(void)
   {
      static int8 loop = LOOPCNT;
      static int8 pulse;
   
      if(--loop == 0)
        {
         loop = LOOPCNT;
         pulse = width;
        }

      if(pulse)
        {
         output_high(PWM_PIN);
         pulse--;
        }
       
      else
      output_low(PWM_PIN);
   
   }
   
void Set_PID ()
   {
   
   }
   
void main()
   {
      setup_counters(RTCC_INTERNAL, RTCC_DIV_1);
      clear_interrupt(INT_RDA);
      enable_interrupts(INT_RDA);
      enable_interrupts(INT_RTCC);
      enable_interrupts(GLOBAL);
           
      while (SI_Flag == 0)
         {
            Output_toggle(Wait_LED);    // Waiting for speed_ref LED
            Delay_ms(100);
         }
            Output_low(Wait_LED);      // Ensure waiting LED off
             
      PWM_Width = 10; // temperary

         while (1);
            {
               if (SI_Flag == 1)
                  {
                     disable_interrupts(GLOBAL);
                     Speed_Reference = Speed_Value;
                     enable_interrupts(GLOBAL);
                     Output_High(Run_LED); // Running LED on
                     SI_Flag = 0;
                  }
                 
               if (CCP1_Flag == 1)  // New speed ref recieved
                  { Set_PID(); }    // Set PWM_Width in here PWM_Width<LOOPCNT
               
               // Output_toggle(Pin_A2);  // to test it is cycling
               // delay_ms(Speed_Reference / 100); // test it is getting speed_ref
            }
   }
Ttelmah
Guest







PostPosted: Sat Apr 19, 2008 9:37 am     Reply with quote

The main fault, is a few lines above the error.
You must not have a ';' at the end of the 'LOOPCNT' definition. This is what is causing the problems.
Some other minor comments.
You need to read out of the serial receive buffer, before you can clear 'INT_RD'. You _cannot_ clear this, unless the buffer is empty. If it has become set, it implies that data is there, and must be read first.
Code:

#INT_RDA
void serial_isr()          // Get serial data
   {
      Speed_Value = getc();
         SI_Flag == 1;
   } 

The line 'SI_Flag==1', compares SI_Flag with '1', and then does nothing with the result. You only want a single '=' here.
Your use of 'long' for the serial receive does nothing. You are receiving 8bit data, so there is nothing 'long' for you to receive....
You haven't got a definition for 'width'. This needs to be a global variable defined before the interrupt handler, into which you put the 'width' count required.

Best Wishes
umka



Joined: 28 Aug 2007
Posts: 99
Location: New Zealand

View user's profile Send private message

PostPosted: Sat Apr 19, 2008 1:55 pm     Reply with quote

thanks ttelmah it compiles now. the set flag was a typo supposed to be single = and the width was supposed to be PWM_Width but forgot to change when changing to original code.

what does having a ; after a #define do?

in the #use rs232 i have defined lond_data so i thought this would allow 16bit data to be sent. i need to send a speed reference of 0 to 35000 so need a long.

I do not understand how to implement the problem you say i will have with the recieve buffer. surely the buffer will be empty appon startup of the micro or do i need to clear the interupt only after i have enabled it?

thanks for the help
Guest








PostPosted: Sat Apr 19, 2008 4:36 pm     Reply with quote

it means that anytime the compiler sees LOOPCNT is will replace it with "(30);" In an assignment that is not a problem:
x = LOOPCNT; which is
x = (30);;
But what happens if you
if (x == LOOPCNT) which is
if (x == (30);)

You will surely get an error.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Sat Apr 19, 2008 4:37 pm     Reply with quote

it means that anytime the compiler sees LOOPCNT is will replace it with "(30);" In an assignment that is not a problem:
x = LOOPCNT; which is
x = (30);;
But what happens if you
if (x == LOOPCNT) which is
if (x == (30);)

You will surely get an error.
Mechanical Engineer
Guest







PostPosted: Tue May 19, 2009 6:23 am     Reply with quote

Hello ,
I am working on a project with 3 servo motors and each has a different duty cycle. I am working with 16F877A pic .Since all the programming world is very strange for me ,I am trying to understand how to use software pwm using the PCM programmer's code above. Is there any way I can use such a code for 3 different duty cycles same time?

Thank you for the help.
bungee-



Joined: 27 Jun 2007
Posts: 206

View user's profile Send private message

PostPosted: Tue May 19, 2009 7:03 am     Reply with quote

Mechanical Engineer wrote:
Hello ,
I am working on a project with 3 servo motors and each has a different duty cycle. I am working with 16F877A pic .Since all the programming world is very strange for me ,I am trying to understand how to use software pwm using the PCM programmer's code above. Is there any way I can use such a code for 3 different duty cycles same time?

Thank you for the help.

I have posted an servo routine (8 servos) for the 18F4550, but it should not be hard to rewrite it to 16F877A ....

The code is HERE Wink
Mechanical Engineer
Guest







PostPosted: Tue May 19, 2009 9:31 am     Reply with quote

Thank u,but I am not sure how it helps me.
Another question , is there a calculation that i need to make for the right LOOPCNT?
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Thu Dec 05, 2013 5:39 pm     Reply with quote

Why the LOOPCNT = 39?

How did you get that number? I debugged and understand the code. But this 39 I can not understand.

I am trying to make a soft pwm 1 to 30 hz....

bye
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