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

Stepper Motor Start and Stop Pulse Profile[SOLVED]
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
erhane



Joined: 01 Jul 2014
Posts: 41

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

Stepper Motor Start and Stop Pulse Profile[SOLVED]
PostPosted: Wed Jul 09, 2014 10:57 am     Reply with quote

Hello,

I am trying to generate pulses for stepper motor drive application with dspic and pic16f familiy.

I have problems with start and stop pulse profiles. I want to start and stop smoothly. That is why tried to produce pulses like ramp but could not succed.

I tried it like
Code:

int x=2000;
While(x>100)
{
output_high(pin);
delay_us(x);
output_low(pin);
x-=1;
}

this loop not working like linear. It is like exponential and fastening immediately.

What is the reason and can you suggest any solutions.

I thought about producing an array and get delay times from that array but speed of stepper motor changes randomly according to user and every speed has its own start and stop profile.

Thank You.


Last edited by erhane on Thu Jul 10, 2014 1:34 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Wed Jul 09, 2014 11:22 am     Reply with quote

Normally what you do is have a 'tick' interrupt that just pulses the controller.
This is called perhaps 50000 times per second.

This has a counter, and only generates a pulse when the counter reaches/exceeds the value in a global variable. The counter is reset at this point.

So if you ramp this variable, the pulse rate will change.

You start with a value in this, corresponding to the speed that the controller can be stepped from a cold start, without losing a step. The pull in speed.
You then ramp this linearly down to the value needed to give the speed you want. Leaving it at this value, then gives a constant speed. When you want to slow, you ramp it back linearly up to the pull in value, then stop.
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Jul 09, 2014 1:48 pm     Reply with quote

hmm..

int x=2000;

Integers in CCS are by default 8 bits......

also

without a delay after the output_low(....)..
you will not get a nice square wave.



jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Wed Jul 09, 2014 2:25 pm     Reply with quote

He shouldn't need a square wave.
Since he is not outputting a bit pattern, he is using a step/direction controller board. All he needs is a tiny pulse (1uSec typically), at a varying frequency.

However the basic approach is wrong. He needs to be running a state machine, and moving through stopped, accelerate, at speed, decelerate, stopped phases. These should be controlled by the outer code loop, and then the timings generated from a tick as outlined.

Have done it many hundreds of times, for different applications, ranging from milling machines, to fans.
erhane



Joined: 01 Jul 2014
Posts: 41

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

PostPosted: Wed Jul 09, 2014 11:51 pm     Reply with quote

Ttelmah, thank you for your reply.

Are you talking about timer interrupt?
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Thu Jul 10, 2014 1:26 am     Reply with quote

Yes, a 'tick', is an interrupt that occurs a a regular interval (just like the tick of a clock).

This is partially trimmed code from a working system, so may well have things typed wrong, or bits missing (the system controls four motors).

What you do, is something like:

Code:

#define PULL_IN 2000
int16 motor=0;
int16 mramp=PULL_IN; //This will depend on the pull in step rate
//of your controller/motor combination, and on the tick rate used.
int1 at_speed=FALSE;
#define STEP_PIN pin_xx //Pin that steps the controller
#define MIN //minimum number of clock cycles the step pin needs

#INT_TIMERx //ideally at a high rate, like 50K/sec.
void tick(void)
   static int16 motor_tick=0;
   if (motor_tick)
      --motor_tick;  //do nothing this time
   else
   {
      if (motor!=0) //there is a speed required
      {
          output_low(STEP_PIN);
          if (motor!=mramp) //changing speed
          {
              if (mramp>motor) //speeding
              {
                  --mramp; //step faster
                  motor_tick=mramp;
              }
              else
              {  //slowing
                  ++mramp; //step slower
                  if (mramp>=MIN)
                     motor=0; //stop next cycle
                  motor_tick=mramp;
              }
          }
          else
          {
              motor_tick=motor; //holding speed
              at_speed=TRUE; //signal the main code that speed is reached.
          }
          delay_cycles(MIN);
          output_high(STEP_PIN);
      }
   }
}

//The main then sets  up the timer to tick.
//Writing a tick count to motor, makes it start accelerating _to_ this count
//From the speed defined as 'MRAMP'.
//So with 50000* per sec, with the 2000 given, it'll start stepping at 25Hz.
//If you want 5KHz as the running speed,
//then motors=9, will give this. The speed will ramp to this rate, then
//at_speed will be set true.
//So:
    motor=9; //select for the speed you want
    while (!at_speed)
    {
        //do what you want while waiting for the motor
    }
    //now the motor is being stepped steadily at the requested speed
    //do what you want here

    //Then to stop:
    motor=MIN;
    while(motor!=0)
    {
        //do what you want while it decelerates
    }
    //Now motor has stopped.

Now the controller will have a minimum pulse width needed on the step pin. If this is (say) 1uSec, and your CPU is running at 60MHz, then this is 30 instruction cycles (DsPIC). The test for motor==0 will take perhaps four cycles, and the loading of the register takes another four cycles, so the pulse must be kept low for another 22 cycles to guarantee to meet this time. This is the value 'MIN'.
This requires a delay in the ISR, and this must be short. Delay_cycles avoids
interrupts being disabled in delays in the main code, and is ideal for the short delay required.
The exact value will depend on the code (I haven't checked the instruction count as posted, my code on which this is based, is fractionally different), on the CPU speed, and on the controller being used.
erhane



Joined: 01 Jul 2014
Posts: 41

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

PostPosted: Thu Jul 10, 2014 1:35 am     Reply with quote

Thank you! i will work on it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Thu Jul 10, 2014 2:04 am     Reply with quote

I wouldn't have added the 'solved' tag, till you have it working!....
Smile
erhane



Joined: 01 Jul 2014
Posts: 41

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

PostPosted: Thu Jul 10, 2014 2:27 am     Reply with quote

Hahahaha i know it will not that easy :D

But i got the point "what i have to work on". That is why i tag it as solved.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Thu Jul 10, 2014 2:33 am     Reply with quote

One thing I missed, is that you have to set 'at_speed' to FALSE, after loading the speed you want it to accelerate to, and before testing....
erhane



Joined: 01 Jul 2014
Posts: 41

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

PostPosted: Thu Jul 17, 2014 1:25 am     Reply with quote

Which interrupt should i use do you think?
I mean i get assumed pulse periods with both timer1 and timer2 interrupts. Is there any differences? I saw some topics which says timer2 interrupt is used for PWM projects.

Thank You
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Thu Jul 17, 2014 1:39 am     Reply with quote

The key point about timer2, compared to any other normal timer on the PIC16/18, is that it is self resetting. So you can program timer2, to give an interrupt 'at' a specific interval, while the other timers can't do this. On the other timers, you have to 'fiddle' by adding a value to the count register on each interrupt. The self resetting ability, is there, so this timer can be used as the source for PWM, but it also makes it the most useful timer for a constant frequency high speed 'tick'.
Some of the later PIC18's have a second timer with this ability (the chips that have timer4).
Timer2(or 4 if it exists), is the best timer for this job. Even if using PWM, you can program this timer to interrupt at a number of counts of the PWM.
erhane



Joined: 01 Jul 2014
Posts: 41

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

PostPosted: Thu Jul 17, 2014 8:02 am     Reply with quote

I know this is a simple question :D

Is this enough to enable interrupt?

setup_timer_2(T2_DIV_BY_16,255,16);


and use
#INT_TIMER2

I could not interrupt.

This is my fuses and main code. My aim is just produce square wave at output with timer interrupt.

Code:

#FUSES INTRC_IO      // Internal RC clock (OSC1 and OSC2 pins are normal I/O)
#FUSES NOWDT         // Watch Dog Timer disabled
#FUSES PUT           // Power Up Timer enabled
#FUSES NOMCLR        // Master Clear pin is used for I/O
#FUSES PROTECT       // Code protected from reads
#FUSES CPD           // Data EEPROM code protected
#FUSES BROWNOUT      // Brownout Reset enabled
#FUSES BORV25        // Brownout Reset at 2.5V
#FUSES NOCLKOUT      // Disable clock output on OSC2
#FUSES NOIESO        // Internal External Switch Over Mode disabled
#FUSES NOFCMEN       // Fail-safe clock monitor disabled
#FUSES WRT           // Program memory write protected                                             
#FUSES NOLVP         // Low Voltage Programming disabled


#INT_TIMER2
void interrupt()
{
   output_toggle(DRV_STEP);
}

void main()
{

// Set I/O states of the ports
   //           76543210                 
   set_tris_a(0b00101000);       
   set_tris_b(0b11001111);

   // Set alternative pin functions
   set_pins();
   // Set SPI parameters
   set_SPI();
   
   // Set variables to default values
   set_variables();
   // Set driver variables to default values
   set_driver();
   motion_cycle();
   fprintf(RS232,"calisiyor\n\r");
   //homing_cycle();
   //enable_interrupts(global);
   //enable_interrupts(INT_RDA);
   setup_timer_2(T2_DIV_BY_16,255,16);
   set_timer2(0);
   while(true)
      {   
           
      }
     
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Thu Jul 17, 2014 2:50 pm     Reply with quote

To 'enable' the interrupt, you have to enable the interrupt....
You are _generating_ a 'potential' interrupt source, but not telling the chip to respond to it.

enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER2);

The chip will then respond to the interrupt.

However assuming you are using a stepper that supports a reasonably high step rate at full speed, you need a much higher interrupt rate.

You don't tell us your CPU clock rate, but assuming (say) 32MHz, then the settings you have would only give about 130Hz. I use 20 to 50kHz for this type of control....
erhane



Joined: 01 Jul 2014
Posts: 41

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

PostPosted: Fri Jul 18, 2014 4:34 am     Reply with quote

I thing we are doing something wrong. I apply our code but ramp is not linear :/The problem is about Floating point probably :/ i assumed i can remove floating problem with timer interrupt but couldnt :D
You can watch it in here:

http://www.youtube.com/watch?v=ES9yUw-Z0zk&feature=youtu.be

And here is code:


Code:

#INT_TIMER2
void interrupt()
{
   
   if (motor_tick)
      --motor_tick;  //do nothing this time
   else
   {
      if (motor!=0) //there is a speed required
      {
          output_low(STEP_PIN);
          if (motor!=mramp) //changing speed
          {
              if (mramp>motor) //speeding
              {
                  --mramp; //step faster
                  motor_tick=mramp;
              }
              else
              {  //slowing
                  ++mramp; //step slower
                  if (mramp>=MIN)
                     motor=0; //stop next cycle
                  motor_tick=mramp;
              }
          }
          else
          {
              motor_tick=motor; //holding speed
              at_speed=TRUE; //signal the main code that speed is reached.
          }
          delay_cycles(MIN);
          output_high(STEP_PIN);
          integer--;
      }
   }
}

void main()
{

// Set I/O states of the ports
   //           76543210                 
   set_tris_a(0b00101000);       
   set_tris_b(0b11001111);

   // Set alternative pin functions
   set_pins();
   // Set SPI parameters
   set_SPI();
   
   // Set variables to default values
   set_variables();
   // Set driver variables to default values
   set_driver();
   motion_cycle();
   fprintf(RS232,"calisiyor\n\r");
   //homing_cycle();
   enable_interrupts(global);
   enable_interrupts(INT_RDA);
   enable_interrupts(INT_TIMER2);
   setup_timer_2(T2_DIV_BY_16,5,4);
   set_timer2(0);
   ///////////////////////////////////////////////////////////////////
    motor=9; //select for the speed you want
    fprintf(RS232,"rampada\n\r"); //do what you want while waiting for the motor
    while (!at_speed)
    {   
      while(integer!=0);
    }
    //now the motor is being stepped steadily at the requested speed
    //do what you want here
   fprintf(RS232,"ulasti\n\r"); //do what you want while waiting for the motor
    //Then to stop:
    motor=MIN;
    while(motor!=0)
    {
        fprintf(RS232,"yavasliyor\n\r"); //do what you want while waiting for the motor//do what you want while it decelerates
    }
 ///////////////////////////////////////////////////////////////////////////////     
}
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