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 speed control, need help

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



Joined: 11 Jan 2012
Posts: 39

View user's profile Send private message

Stepper motor speed control, need help
PostPosted: Tue Feb 14, 2012 12:35 pm     Reply with quote

Hello, I need to control the speed on a stepper motor. I use this method:

Code:

void speed(int32 x){
   output_low(PIN_B4);
   output_high(PIN_B2);
   output_high(PIN_B5);
   delay_us(x);
   output_low(PIN_B5);
   output_high(PIN_B2);
   output_high(PIN_B3);
   delay_us(x);
   output_low(PIN_B2);
   output_high(PIN_B3);
   output_high(PIN_B4);
   delay_us(x);
   output_low(PIN_B3);
   output_high(PIN_B4);
   output_high(PIN_B5);
   delay_us(x);
}


Where "x" controls speed. (if it is 1300 is like full speed, as I increase from 1300 the speed is slowly down).

I have two questions:

1) I don't have any previous experience with stepper motors, is this way correct to control the speed of motor?

2) This works good if the program only runs "speed" method, if the program have more code, the speed is completely different. I think its because all delays will be different, because program lose time running other code, and it destroys the results I expected from running "speed" alone. So the question is why I make this "delays" only in speed method? Without stopping rest of the program? (I think the problem is on it).

Thanks for help
asmboy



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

View user's profile Send private message AIM Address

PostPosted: Tue Feb 14, 2012 1:44 pm     Reply with quote

Quote:

( int32 x)

delay_us(x)


1- using delay statements is not the best programming practice
IMHO - timers were crated to do that sort o thing
2- read your CCS manual about the allowable range of argument for the delay function

3-because there is no schematic posted - i have no way to know for sure
if your code makes any sense at all is

4- what is your idle state the same as the last change in the code ??

5- what i DO know is that IF it actually CAN work at all - it will only step ONE WAY
temtronic



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

View user's profile Send private message

PostPosted: Tue Feb 14, 2012 1:48 pm     Reply with quote

1) There is no 'correct' way. How you control stepping motors depends on application, speed, torque, resources, etc.

2) Using delays from a programming perspective is 'wrong' as the PIC has to 'twiddle it's thumbs' wasting time when it could be doing something else. That's one reason ISRs are popluar and necessary. In small, simple programs 'killing time' in a delay_ms() is 'ok' but the more complex a program gets (reading sensors, doing math, controlling several 'things') the sooner you find out hard coded delays are 'bad'.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

stepper motor control
PostPosted: Tue Feb 14, 2012 3:42 pm     Reply with quote

Yes, changing the time interval between steps is one way to control speed. You've already realised that you can't do anything else when you use instructions of the delay_us() variety.

One answer is to use interrupts to regulate the timing between steps. Then you don't force the processor to twiddle its thumbs waiting for the next advance.

You need a more generic way of controlling the steps so that it's easier to do things like generating compact code, reversing direction, and create smoother speed changes.

What more do you need to know?

Mike
Chaud



Joined: 11 Jan 2012
Posts: 39

View user's profile Send private message

PostPosted: Tue Feb 14, 2012 7:29 pm     Reply with quote

Thanks for replies guys, they were very useful for me. Tomorrow I will try to change delay_us() for interrupts. I have already a interrupt:
Code:

#int_RTCC
void RTCC_isr(void){
   count++;
}

This count will increment every 51.2 us, if I want to delay motors 1300 us, in speed method I need to change delay_us for something that "waits" for count do get value "25" (51.2 x 25 = ~ 1300), will it work as I want this way? The "wait" function, which I still need to discover if it exists, will stop the program? Or I need to run speed method inside the interrupt??

Asmboy the schematic is simple, I have a stepper motor with 5 wires, 4 connected to motor driver which is ULN203AN, the other one is VCC , and from ULN203AN they are connected to respective PIC pins, which are B2,B3,B4,B5.

This schematic is just for testing motors, but what I pretend to do with motors, is controlling speed with a PID controller, which inputs come from a gyroscope.

Something like this:

Motor acceleration = Kp * Angle + Kd * Angular velocity , its a balancing robot.

Mike you said "its one way to control speed". What are the other ways? And which one do you advise me for my purposes?

Thanks for help Smile
RoGuE_StreaK



Joined: 02 Feb 2010
Posts: 73

View user's profile Send private message

PostPosted: Tue Feb 14, 2012 9:04 pm     Reply with quote

How about this one (thoroughly untested):
Code:
int1 doMotor = 1; //do straight away
int8 motorSector = 0; //do 1st sector
int8 motorSpeed = 25;
int8 count = 0;

#int_RTCC
void RTCC_isr(void)
{
   count++;
   if(count > motorSpeed)
   {
      motorSector < 3 ? motorSector++ : motorSector = 0;
      doMotor = 1;
   }
}



void main()
{
   while(1)
   {
      if(doMotor)
      {
         switch(motorSector)
         {
            case 0:   output_low(PIN_B4);
                  output_high(PIN_B2);
                  output_high(PIN_B5); break;
            case 1:   output_low(PIN_B5);
                  output_high(PIN_B2);
                  output_high(PIN_B3); break;
            case 2:   output_low(PIN_B2);
                  output_high(PIN_B3);
                  output_high(PIN_B4); break;
            case 3:   output_low(PIN_B3);
                  output_high(PIN_B4);
                  output_high(PIN_B5); break;
         }
         doMotor = 0;
      }
   }
}
Do 1st sector straight away, then loop away madly in Main until the ISR counter goes over your "motorSpeed" setting, which sets a flag and increments the sector. Main sees the flag, reads the sector, and does that bit of driving.
This way, you can do whatever else you want in Main etc., and not get caught up with delays.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

motor control
PostPosted: Wed Feb 15, 2012 6:51 am     Reply with quote

Hi Chaud,

OK. So you've got a bi-polar stepper motor to drive for a project. You appear to be driving in full step mode. You've been given some big hints on how to get round your problem of the timing clogging up the processor.

Stepper motors are a big field. I don't want to get involved in doing a seminar on stepper motor drives. In my day we had to work it all out for ourselves. In the last few minutes I've looked on google and wiki. There's loads of stuff out there. All pre-prepared and ready to go. Explains about single-step, half-step, full-step, and micro-stepping methods. You need to cut some code, make mistakes and learn from them. That way you'll end up a lot better engineer. The guys on this forum are not going to give you fully working code.

It's already been said "there is no best method". What you need depends on your resources and the demands of your particular project. You will have to make decisions, run the risk they may be wrong (or not quite good enough), and be prepared to start again or back-track a little.

If you start trying to do the impossible then you WILL get stuck. When that happens we're willing to give you a helping hand by suggesting hints and work-rounds. Don't make things difficult for us. I don't want to wade through mountains of code to find a typo. When you want help, write a short program which highlights the problem or explain with just enough detail what's happening. Bear in mind nobody is going to build a copy of your robot, just to try out your code.

Mike
Chaud



Joined: 11 Jan 2012
Posts: 39

View user's profile Send private message

PostPosted: Thu Feb 16, 2012 12:36 pm     Reply with quote

RoGuE_StreaK wrote:
How about this one (thoroughly untested):
Code:
int1 doMotor = 1; //do straight away
int8 motorSector = 0; //do 1st sector
int8 motorSpeed = 25;
int8 count = 0;

#int_RTCC
void RTCC_isr(void)
{
   count++;
   if(count > motorSpeed)
   {
      motorSector < 3 ? motorSector++ : motorSector = 0;
      doMotor = 1;
   }
}



void main()
{
   while(1)
   {
      if(doMotor)
      {
         switch(motorSector)
         {
            case 0:   output_low(PIN_B4);
                  output_high(PIN_B2);
                  output_high(PIN_B5); break;
            case 1:   output_low(PIN_B5);
                  output_high(PIN_B2);
                  output_high(PIN_B3); break;
            case 2:   output_low(PIN_B2);
                  output_high(PIN_B3);
                  output_high(PIN_B4); break;
            case 3:   output_low(PIN_B3);
                  output_high(PIN_B4);
                  output_high(PIN_B5); break;
         }
         doMotor = 0;
      }
   }
}
Do 1st sector straight away, then loop away madly in Main until the ISR counter goes over your "motorSpeed" setting, which sets a flag and increments the sector. Main sees the flag, reads the sector, and does that bit of driving.
This way, you can do whatever else you want in Main etc., and not get caught up with delays.


Thanks for this, the solution isnt that, but after some tests i figured out that i must use motor control inside interruption,because it need to be controlled with "timers" at same time main program runs, only solution for that is interruptions, so your code still helped alot Smile

Mike Walne i agree with you, was what i did now, this reply is to say thanks for help because i think my problem is solved,after many tests. But if people got instant answer without losing time i dont see where is the problem of giving that, even if it is code, its our problem if we learn less or more with that, not your, but thanks for advises!
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Code
PostPosted: Thu Feb 16, 2012 2:29 pm     Reply with quote

Hi Chaud,

Thanks for your response. It's not simply that I'm unwilling to provide code.

This is my style:-

You ask a question.

I have several choices including:-

(1) Give a complete answer which can be used with no further effort on your part. You go away, learn very little or even nothing, come back again in a few weeks time with the same or a similar question.
(2) I ask YOU a question, make YOU think about the problem in a different way and arrive at AN answer by your own efforts.
(3) Give a partial solution but leave out LOTS of missing pieces.

What do you think?

Sorry, it's my style. It probably takes more effort on my part to go down the routes 2 & 3, but it's the way I do things, and have for quite some time. You have to realise there is usually more than one acceptable reponse to engineering questions. So why should I impose my ideas on you, when some of mine are very MUCH more than half a century old?

Don't forget that I may not have seen the device you're working with, but have seen the the same, or a similar problem, in the past on something that's now obsolete. Universal laws (Ohm, Nyquist, Thevenin, Sod, etc) do not change very rapidly, so are applicable for a very long time.

Mike
Chaud



Joined: 11 Jan 2012
Posts: 39

View user's profile Send private message

Re: Code
PostPosted: Thu Feb 16, 2012 5:43 pm     Reply with quote

Mike Walne wrote:
Hi Chaud,

Thanks for your response. It's not simply that I'm unwilling to provide code.

This is my style:-

You ask a question.

I have several choices including:-

(1) Give a complete answer which can be used with no further effort on your part. You go away, learn very little or even nothing, come back again in a few weeks time with the same or a similar question.
(2) I ask YOU a question, make YOU think about the problem in a different way and arrive at AN answer by your own efforts.
(3) Give a partial solution but leave out LOTS of missing pieces.

What do you think?

Sorry, it's my style. It probably takes more effort on my part to go down the routes 2 & 3, but it's the way I do things, and have for quite some time. You have to realise there is usually more than one acceptable reponse to engineering questions. So why should I impose my ideas on you, when some of mine are very MUCH more than half a century old?

Don't forget that I may not have seen the device you're working with, but have seen the the same, or a similar problem, in the past on something that's now obsolete. Universal laws (Ohm, Nyquist, Thevenin, Sod, etc) do not change very rapidly, so are applicable for a very long time.

Mike


Yes i agree with you, and i understand your style Smile, giving hints and not direct answer make people think and learn
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