|
|
View previous topic :: View next topic |
Author |
Message |
Chaud
Joined: 11 Jan 2012 Posts: 39
|
Stepper motor speed control, need help |
Posted: Tue Feb 14, 2012 12:35 pm |
|
|
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
|
|
Posted: Tue Feb 14, 2012 1:44 pm |
|
|
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: 9226 Location: Greensville,Ontario
|
|
Posted: Tue Feb 14, 2012 1:48 pm |
|
|
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
|
stepper motor control |
Posted: Tue Feb 14, 2012 3:42 pm |
|
|
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
|
|
Posted: Tue Feb 14, 2012 7:29 pm |
|
|
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 |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Tue Feb 14, 2012 9:04 pm |
|
|
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
|
motor control |
Posted: Wed Feb 15, 2012 6:51 am |
|
|
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
|
|
Posted: Thu Feb 16, 2012 12:36 pm |
|
|
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
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
|
Code |
Posted: Thu Feb 16, 2012 2:29 pm |
|
|
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
|
Re: Code |
Posted: Thu Feb 16, 2012 5:43 pm |
|
|
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 , giving hints and not direct answer make people think and learn |
|
|
|
|
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
|