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

Step Counting using pwm.
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
bruno.gf



Joined: 26 Jan 2010
Posts: 9

View user's profile Send private message

Step Counting using pwm.
PostPosted: Tue Jan 26, 2010 5:35 pm     Reply with quote

Hello everyone,

I used the search tool and didn't find anything about this.

I'm not from America so, sorry for my bad english.

When I don't use PWM to activate my stepper motor, I can easily count the steps, example:
Code:

output_high (PIN_B0);
delay_ms (200);
output_low (PIN_B0);
i++;

printf("Steps: %u", i); // "i" is the number of steps;

But I want to use PWM and count the steps!! Is that possible??

PWM makes the PIN goes high ( value of 1 ) and low ( value of 0 ) by pulsing, I was wondering if there is any function that detects when the pin goes high so I can make my step counting variable ( "i" ) increases in one unit every time this happens.

Thank you people,
Best Wishes.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jan 26, 2010 5:50 pm     Reply with quote

If your PWM frequency is slow enough (or the PIC's oscillator frequency
is high enough), you could use the #int_timer2 interrupt to increment a
global counter variable. The reason for the concern about speed is
because the interrupt handler takes about 40 to 50 instruction cycles to
get in and out of the interrupt service routine. (i.e., with a 4 MHz crystal,
it would take 40 to 50 usec per interrupt, just for the overhead).
This does not include the instruction cycles that you use in your isr code.

To do this, you need to set the Timer2 postscaler value to 1.
See the setup_timer_2() function in the CCS manual.

Or, I suppose that you could poll the TIMER2 interrupt flag in a software
loop, instead of using interrupts. This would eliminate most of the
overhead. You could use the interrupt_active(INT_TIMER2) function to
test the flag, and the clear_interrupt(INT_TIMER2) function to clear it.
Note that with this method there is no #int_timer2 routine. You also do
not enable INT_TIMER2 or GLOBAL interrupts. You just poll the interrupt
flag.

----
Edit: Corrected the interrupt. Timer2 is the interrupt to check.


Last edited by PCM programmer on Tue Jan 26, 2010 10:46 pm; edited 2 times in total
bruno.gf



Joined: 26 Jan 2010
Posts: 9

View user's profile Send private message

PostPosted: Tue Jan 26, 2010 6:14 pm     Reply with quote

Thank you for the reply PCM Programmer,

I've just read the ccs manual and the functions that you said,

So let me see if i understood,

i should put the "i++" between "interrupt_active(INT_CCP1)" and "clear_interrupt(INT_CCP1)", righ?? Can it be inside of a loop??

Thank You,
Best wishes.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jan 26, 2010 6:26 pm     Reply with quote

I'm testing if this will work. I will post an update later.
bruno.gf



Joined: 26 Jan 2010
Posts: 9

View user's profile Send private message

PostPosted: Tue Jan 26, 2010 6:29 pm     Reply with quote

ok, i'll wait !!

thank you very much !!

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jan 26, 2010 10:23 pm     Reply with quote

Here's an example that puts out the specified number of pulses on
the CCP1 pin. I don't know if this is the best way to do this (putting
out a specific number of pulses), but it was fun to do. Note that I've
corrected my post above. The interrupt flag that must be checked is
the Timer2 interrupt.

To end the sequence of pulses, you must set the PWM duty cycle to 0.
If you just call setup_ccp1() with CCP_OFF, you will get a short pulse
for the last pulse. But if you set the duty cycle to 0 when the desired
number of pulses has occurred, the last pulse will be the correct duration.
Code:

#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#define NUM_PULSES  10

//======================================
void main()
{
int16 count;

// Setup CCP1 for PWM at 244 Hz and 50% duty cycle.
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 255, 1); 
set_pwm1_duty(128);

count = 0;

// Do the specified number of pulses on CCP1 and then stop.
while(1)
  {
   if(interrupt_active(INT_TIMER2))
     {
      clear_interrupt(INT_TIMER2);     
      count++;
      if(count == NUM_PULSES)
        { 
         set_pwm1_duty(0);  // Set PWM output = constant 0
         break;
        }
     }
  }

while(1);
}
Guest








PostPosted: Wed Jan 27, 2010 8:32 am     Reply with quote

Now i understood !!!

Thank You PCM Programmer !!

I'll put a "printf" function in this code .

When i put the printf to count steps or turns, the motor got VERY slow, thats because i was writing the "printf" function in the middle of the steps of my motor. Now it shouldn't happen because i won't stop the pulse on pwm pin to write on lcd, right???

Best Wishes.
bruno.gf



Joined: 26 Jan 2010
Posts: 9

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 8:33 am     Reply with quote

The post above was mine, i forgot to login
Sorry.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 12:31 pm     Reply with quote

The polling method requires a tight loop. You can't put delays in the
loop that are longer than the PWM period. If you want to have the
PIC do something else (other than sit in a polling loop), then you need
to use #int_Timer2 interrupts and have it do this part of the code
inside the isr:
Code:

count++;

if(count == NUM_PULSES)
  { 
   set_pwm1_duty(0);  // Set PWM output = constant 0
  }
bruno.gf



Joined: 26 Jan 2010
Posts: 9

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 2:20 pm     Reply with quote

Ok PCM Programmer, so based on what you said, I made my program, do you see anything that can probably goes wrong??
Code:

#include <16F628A.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#include <tutorial.c> // Includes my lcd library
#use rs232(baud=9600, xmit=PIN_A6, rcv=PIN_A7, ERRORS)

//======================================
void main()
{
int16 count;

// Setup CCP1 for PWM at 244 Hz and 50% duty cycle.
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 255, 1);
set_pwm1_duty(128);


portb = 0; //reset

set_tris_b(0b11111111); //  direction of pins I/O

inicializa_lcd();  // Inicializes the LCD

count = 0;

// Writes on lcd the steps
while(TRUE)
  {
   if(interrupt_active(INT_TIMER2))
     {
      clear_interrupt(INT_TIMER2);     
      count++;
      printf(escreve_lcd,("Steps: %Lu", count)); // Writes to LCD the number of steps

   }
   
  }

}

I used part of your code and put some functions.

Thank you !!

Best wishes.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 2:44 pm     Reply with quote

I don't know what you are trying to do, since you never stop the PWM
after a specified number of pulses. You just let it keep running forever.

Quote:
set_tris_b(0b11111111);

Also, you are setting the TRIS for PortB to be all inputs. The 16F628A
data sheet specifically says that the CCP1 pin must have the TRIS set
for Pin B3 so it's an output pin. The CCS compiler automatically handles
doing this. Delete that line.

Also, you never reset the X,Y cursor location of the LCD, so it will
soon write characters off the end of the LCD.
bruno.gf



Joined: 26 Jan 2010
Posts: 9

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 3:27 pm     Reply with quote

I'm trying to count the steps, whitout stopping my motor. I just took of the part where you did "duty cycle = 0".

I have a question: Is there any possibility the function "printf" make slow my motor???

I'll take of that line as you said and i'll correct the lcd error.

Thank You

Best Wishes.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 3:36 pm     Reply with quote

Quote:

Is there any possibility the function "printf" make slow my motor???

If you want to test if it slows down the motor, then comment it out.
See if the motor speed changes when you do that. In other words,
you control the program. Do some testing. Do some debugging.
bruno.gf



Joined: 26 Jan 2010
Posts: 9

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 3:48 pm     Reply with quote

Ok i'll send it to PIC, make the tests and post here the results.

Thanks for your help!!

Best Wishes
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Wed Jan 27, 2010 10:51 pm     Reply with quote

You know, you could run another timer, with a period set to 10 or 100 times the TMR2 repetition rate, and count tens or hundreds of motor steps, then if you get close to the stopping point, drop down to counting every TMR2 pulse. That way you wouldn't be constrained by the TMR2 interval all the time. Just a thought.
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