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

Speed up a loop driving a stepper motor

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



Joined: 28 Jul 2020
Posts: 31

View user's profile Send private message

Speed up a loop driving a stepper motor
PostPosted: Thu Oct 20, 2022 7:47 am     Reply with quote

Hello, I'm trying to speed up a loop in charge of generating pulses to a stepper motor. The goal was to achieve 6ms for one loop on a 18F6722.
I started from this
Code:
int32 step;
int16 ramp;
int16 delay;
int16 pin;
for( step = 0; step < ramp; step++ )
{
    output_high(pin);
    delay_us(delay);
    output_low(pin);
    delay_us(delay);
}

Then read the doc that explains output_high/low are much slower when using variables;
Went to
Code:
int32 step;
int16 ramp;
#define PIN_A1 30000
for( step = 0; step < ramp; step++ )
{
    output_high(PIN_A1);
    delay_us(delay);
    output_low(PIN_A1);
    delay_us(delay);
}

Then noted the mix of int16/int32 was slower than 2 int32
Code:
int32 step;
int32 ramp;
#define PIN_A1 30000
for( step = 0; step < ramp; step++ )
{
    output_high(PIN_A1);
    delay_us(delay);
    output_low(PIN_A1);
    delay_us(delay);
}

Now I have noticed that
1. delay_us is also slower when using a variable
2. the loop itself takes a few msec (increment + comparison + code jump I suppose)
3. ++step is slower than step++

Where can I improve the code? Point 1. is the most problematic right now. I cannot hardcode the delay. How can I avoid delay_ms(delay) to take 4msec instead of 1 when delay=1 ?

Thanks in advance
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Oct 20, 2022 11:42 am     Reply with quote

Start by telling us what clock rate your chip is running?. Critical data.
Then what you actually want to do?. Obviously you actually want the speed
to be changeable (otherwise you would not be using a variable), and you
also appear to want to be able to drive more than one pin. These are all
things we need to know before we can help.
Honestly, if you are just pulsing a few pins, use hardware. PWM or CCP.
Both are capable of doing pulses accurately, and hundreds of times faster
than software can manage.
julienm



Joined: 28 Jul 2020
Posts: 31

View user's profile Send private message

PostPosted: Thu Oct 20, 2022 3:36 pm     Reply with quote

THe PIC runs at 20MHz.
I want to program a trapezoid stepper command (with customisable ramp up and ramp down) that can run on 2 different motors (hence the original variable for the PIN).
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Thu Oct 20, 2022 8:27 pm     Reply with quote

Seriously, reevaluate your approach and use CCP (PWM mode) or a dedicated PWM peripheral. Bit-banging it, as you've discovered, has its limitations.
julienm



Joined: 28 Jul 2020
Posts: 31

View user's profile Send private message

PostPosted: Thu Oct 20, 2022 11:56 pm     Reply with quote

Well thanks for the comments but
- I have to work with this hardware, redesigning is not possible
- would PWM allow me to vary linearly vary the frequency at high speed? I don't want a stable pwm
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 12:34 am     Reply with quote

Yes, and much easier.

Key problem with the variable delay approach, is that the delay is changing
with each loop. Result it becomes really hard to give a linear speed change.

With the PWM, all you do is have a timer interrupt at (say) 100Hz, and a
table of speed values, and if the stepper state is 'ACCELERATING', each
time this interrupts you load the next faster value from the table to the
PWM. Result, lovely smooth acceleration. For 'DECELERATING', you do the
same except moving to slower values.

Most PIC's have at least two PWM's. If you can use the pins for these, a
much better solution.
I've got systems here using 'up market' PIC's with more PWM's and giving
STOP, ACCELERATE_TO_SPEED, STEADY_SPEED, DECELERATE_TO_STOP,
on six motors at a time (CNC mill with X,Y,Z, rotary table, dividing head,
and spindle speed, done exactly this way.
julienm



Joined: 28 Jul 2020
Posts: 31

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 1:44 am     Reply with quote

I understand I really need a training on PIC programmation. Because the moment you mention using timers, I'm scared.
Also right now the 4 PWM output are used to drive some LEDs.

Long story short, there's no way to bit-bang faster by telling the compiler my variables should be stored somewhere else for faster access?
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 5:26 am     Reply with quote

There are things you can do.
For example, on the pins, don't use a variable, but use a case.
So have a variable 'pin', and something like:
Code:

#inline
set_pin(int pin)
{
   switch (pin) {
   case 0:
       output_high(PIN_A0);
       break;
   case 1:
       output_high(PIN_A1);
       break;
   case 2:
       output_high(PIN_A2);
       break;
   case 3:
       output_high(PIN_A3);
       break;
}


Also your pin output will be faster if you setup fast_io on the port you
are using.

Do this and 'set_pin(val)' will code about 20 instructions faster than
using the standard output_high(variable) approach.

You are still going to have real problems getting linear acceleration.

Now I'm going to say immediately, use a timer!....

The point is that delay_us, as you have found has minimum times that
can be handled with variables, and also does not know about time that
is being used by the other operations. So, simply use a system timer.
Use #use timer, and it's default 1uSec tick. Then set_ticks(0); before
you turn the pin on, and afterwards, while(get_ticks() < 6000) will
wait 6mSec (6000 1uSec ticks). If you use an array of values to wait
for, you have your variable times.

However much better to use the PWM's.
Seriously, LED's only need slow PWM's. A single 100Hz timer interrupt,
and you could give yourself the LED's all being handled.
You then have the PWM's available for what they are designed for. Fast
pulses. The same timer interrupt can also handle the acceleration and
deceleration.
temtronic



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

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 6:02 am     Reply with quote

a comment....

One potential problem with 'stepping motors' is trying to step them too fast ! You must read the mfrs specs for your motors and code as needed for both maximum speed and pulse widths.

Agree , 'timers' are the way to go.....if you code with 'delay_ms(xxx)', the PIC is stuck doing the delay ,can't do ANYTHING else except twiddle bits until delay is done.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 6:43 am     Reply with quote

Yes. This depends massively on the controller (if it supports microstepping),
the endpoint drive voltage, and the motors themselves. Understand that
to step fast with high power, you probably need a supply that is perhaps
10* the actual rating of the motor to maintain current when stepping fast
into their massive inductance. The 'rule', is usually between 5*, and 24* their
plate voltage.

Have a look at:
[url]
https://www.e-jpc.com/stepper-motor-voltage-explained/
[/url]
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