Motion profile generator.


Closed Thread
Results 1 to 40 of 56

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610

    Default Motion profile generator.

    Hi everyone,
    I'm looking for help and advice on implementing a basic motion profile generator in PBP. Ideal would be 3rd order one (linear acceleration, S-curved velocity) but the simpler 2nd order (trapezoidal acceleration, triangular velocity) proved to be hard enough to get right so I'll settle for that to begin with. Here's a crude drawing illustrating what that type of motion profile looks like:

    Name:  Simple_profile.gif
Views: 21624
Size:  5.4 KB

    I'm trying to base my version on Microchips AN532, the profile generator is covered in detail in appendix E. But I'm obviously running into trouble or I wouldn't be here seeking advise.

    Without looking at any code lets just look at the theory.
    • I have a timer interrupt running, providing a system tick (the frequency doesn't matter here)
    • I have a Position variable which tells the feedback loop where the motor is supposed to be at any given time. The feedback loop plays no actual role here.
    • I have a Target variable which is to where I want the motor to move.
    • I have an acceleration value (A_Max in the above drawing), lets say this value is 10
    • I have a Velocity value which is the desired motor velocity in encoder counts per system tick at any given time.
    • I have a max velocity (V_Max in the above drawing) which is the velocity at which I want the motor to move. Lets say this value is 100

    Now lets look at how easy it is to ramp up or down the motor speed. Initially Velocity is 0:
    Each tick the value of A_Max gets added to the value Velocity. If Velocity > V_Max THEN Velocity = V_Max. The value of Velocity is added to the Position variable.
    This will ramp up the motor from 0 to V_Max and then keep it running at that velocity. Ramping it down is obviosuly equally simple, just subtract A_Max from Velocity and Velocity from Position until Velocity is 0.

    What I'm struggling with is to make it stop at the Target position.

    In the Microchip implementation they begin by dividing the total distance of the move by 2 and store that value. Then they start to accelerate the motor. Now one of two things can happen:
    1) Half the distance is covered before reaching V_Max in which case the motor is decelerated.
    2) The velocity reaches and possibly gets clamped at V_Max before half of the distance is covered.

    In (2) above they count how many ticks the velocity is at V_Max and when half the distance is covered they start subtracting from that count, one tick at the time. When the count is 0 they decelerate the motor. Pretty simple.

    If we do a move of 2000 with A_Max=10 and V_Max=100 then it would look something like this:
    Code:
    Acc	Vel	Pos	
    0	0	0	
    10	10	10	
    10	20	30	
    10	30	60	
    10	40	100	
    10	50	150	
    10	60	210	
    10	70	280	
    10	80	360	
    10	90	450	
    0	100	550	<- At V_Max (1)
    0	100	650	<- At V_Max (2)
    0	100	750	<- At V_Max (3)
    0	100	850	<- At V_Max (4)
    0	100	950	<- At V_Max (5)
    0	100	1050	<- Half distance
    0	100	1150	<- At V_Max (4)
    0	100	1250	<- At V_Max (3)
    0	100	1350	<- At V_Max (2)
    0	100	1450	<- At V_Max (1)
    0	100	1550	<- At V_Max (0)
    -10	90	1640	
    -10	80	1720	
    -10	70	1790	
    -10	60	1850	
    -10	50	1900	
    -10	40	1940	
    -10	30	1970	
    -10	20	1990	
    -10	10	2000
    Perfect! This works because everything is dividing nicely into everything else. But what happens when, for example, A_Max doesn't divide evenly into V_Max?

    Code:
    Acc	Vel	Pos	
    0	0	0	
    15	15	15	
    15	30	45	
    15	45	90	
    15	60	150	
    15	75	225	
    15	90	315	
    15	100	415	<- At V_Max (1)
    0	100	515	<- At V_Max (2)
    0	100	615	<- At V_Max (3)
    0	100	715	<- At V_Max (4)
    0	100	815	<- At V_Max (5)
    0	100	915	<- At V_Max (6)
    0	100	1015	<- Half distance
    0	100	1115	<- At V_Max (5)
    0	100	1215	<- At V_Max (4)
    0	100	1315	<- At V_Max (3)
    0	100	1415	<- At V_Max (2)
    0	100	1515	<- At V_Max (1)
    0	100	1615	<- At V_Max (0)
    -15	85	1700	
    -15	70	1770	
    -15	55	1825	
    -15	40	1865	
    -15	25	1890	
    -15	10	1900	
    -15	0	1900
    Here we end up 100 counts short of the target. I understand WHY it's happening but I can't seem to figure out a good fix for it.

    In the Microchip application note they seem to somehow determine which is resulting in the smallest error, one more or one less "tick" at V_Max. They then, obviously, opt for the one resulting in the least amount of error at the end of the profile and then they're simply "bumping" the motor to the CORRECT target position at the end of the move.

    I really can't have that - I need it to ramp down and end up exactly AT the target position.

    If anyone's got any ideas, pointers, suggestions or codesnippets I'd really appreciate the input, thanks!

    /Henrik.

  2. #2
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    I think the obvious answer is to use floating point math ...
    But then the frequency of your interrupts may become more important. How fast are they?

    Or maybe you could take the remainder of the division and add it in a separate variable on each step, and when that overflows add one to Vel.
    When ramping down, subtract 1 on an underflow instead.
    It's kind of like floating point, as long as you're just adding and subtracting 1 unit each time.
    It's harder to do than the actual floating point, but is probably faster.
    DT

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Thanks Darrel,
    The interrupt rate varies depending on application but up to 2.5kHz.

    I guess by 'the division' you mean V_Max / A_Max ? Or do you mean Distance/2 (I don't think so since the reminder will either be 0 or 1)?
    So, in the previous, non ideal example I'd get 100//15 = 10.

    From there I don't quite follow... If I keep adding 10 to a BYTE variable it'll overflow on the 26th tick which is right at the very end of the profile in that previous example, that can't be right. On the other hand, for the acceleration step:
    Code:
    Accumulator = Accumulator + Reminder
    If Accumulator >= A_Max THEN
      Accumulator = Accumulator - A_Max
      Velocity = Velocity + 1
    END IF
    Is that in line with what you're thinking?

    I need to sleep on this I think. Thanks again!

    /Henrik.

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Well, I was thinking more of the decimal remainder than the modulas remainder.

    But in trying to recreate the code, I'm seeing some big limitations in the theory.
    The only way to end up at the exact Target Position, is to have a Position that is an exact multiple of V_Max.

    With V_Max = 100, you can only get target positions of 1800, 1900, 2000, 2100 etc.
    I would think you would want more precise targets ...

    Currently, I can get +/- 5 counts from those targets by using the decimal remainder idea.
    I think I can change it to reach any target position, but then I see more problems down the road.

    This only ramps from 0 to a target.
    It won't go from target to target.
    Unless there's some other steps in the process that I'm missing.

    Here's some output from the test program.
    If I can figure the rest out, I'll post the code.
    Code:
    1 = Edit Max_Acceleration (10)
    2 = Edit Max_Velocity     (100)
    3 = Edit TargetPosition   (2000)
    Enter = GO
    >
    
        0       0       0   
       10      10      10   
       10      20      30   
       10      30      60   
       10      40     100   
       10      50     150   
       10      60     210   
       10      70     280   
       10      80     360   
       10      90     450   
       10     100     550   
       10     100     650   
       10     100     750   
       10     100     850   
       10     100     950   
       10     100    1050   
       10     100    1150   
       10     100    1250   
       10     100    1350   
       10     100    1450   
       10     100    1550   
       10      90    1640   
       10      80    1720   
       10      70    1790   
       10      60    1850   
       10      50    1900   
       10      40    1940   
       10      30    1970   
       10      20    1990   
       10      10    2000   
       10       0    2000   
    
    1 = Edit Max_Acceleration (10)
    2 = Edit Max_Velocity     (100)
    3 = Edit TargetPosition   (2000)
    Enter = GO
    >1
    Enter new Max_Acceleration (10):15
    
    Max_Acceleration = 15
    
    1 = Edit Max_Acceleration (15)
    2 = Edit Max_Velocity     (100)
    3 = Edit TargetPosition   (2000)
    Enter = GO
    >
    
        0       0       0   
       14      14      14   
       14      28      42   
       14      42      84   
       14      57     141   
       14      71     212   
       14      85     297   
       14      99     396   
       14     100     496   
       14     100     596   
       14     100     696   
       14     100     796   
       14     100     896   
       14     100     996   
       14     100    1096   
       14     100    1196   
       14     100    1296   
       14     100    1396   
       14     100    1496   
       14     100    1596   
       14     100    1696   
       14      86    1782   
       14      72    1854   
       14      58    1912   
       14      43    1955   
       14      29    1984   
       14      15    1999   
       14       0    1999   
    
    1 = Edit Max_Acceleration (15)
    2 = Edit Max_Velocity     (100)
    3 = Edit TargetPosition   (2000)
    Enter = GO
    >3
    Enter new TargetPosition (2000):1800
    
    TargetPosition = 1800
    
    1 = Edit Max_Acceleration (15)
    2 = Edit Max_Velocity     (100)
    3 = Edit TargetPosition   (1800)
    Enter = GO
    >
    
        0       0       0   
       14      14      14   
       14      28      42   
       14      42      84   
       14      57     141   
       14      71     212   
       14      85     297   
       14      99     396   
       14     100     496   
       14     100     596   
       14     100     696   
       14     100     796   
       14     100     896   
       14     100     996   
       14     100    1096   
       14     100    1196   
       14     100    1296   
       14     100    1396   
       14     100    1496   
       14      86    1582   
       14      72    1654   
       14      57    1711   
       14      43    1754   
       14      29    1783   
       14      14    1797   
       14       0    1797   
    
    1 = Edit Max_Acceleration (15)
    2 = Edit Max_Velocity     (100)
    3 = Edit TargetPosition   (1800)
    Enter = GO
    >2
    Enter new Max_Velocity (100):90
    
    Max_Velocity = 90
    
    1 = Edit Max_Acceleration (15)
    2 = Edit Max_Velocity     (90)
    3 = Edit TargetPosition   (1800)
    Enter = GO
    >
    
        0       0       0   
       15      15      15   
       15      30      45   
       15      45      90   
       15      60     150   
       15      75     225   
       15      90     315   
       15      90     405   
       15      90     495   
       15      90     585   
       15      90     675   
       15      90     765   
       15      90     855   
       15      90     945   
       15      90    1035   
       15      90    1125   
       15      90    1215   
       15      90    1305   
       15      90    1395   
       15      90    1485   
       15      90    1575   
       15      75    1650   
       15      60    1710   
       15      45    1755   
       15      30    1785   
       15      15    1800   
       15       0    1800   
    
    1 = Edit Max_Acceleration (15)
    2 = Edit Max_Velocity     (90)
    3 = Edit TargetPosition   (1800)
    Enter = GO
    >
    I'm just going from your description, I haven't tried to convert the original code.

    My questions:
    • Is it supposed to be able to move to any target position? Not just a multiple of V_Max?
    • Is it supposed to move from any position to any other position?
    • Or is that part handled in your routines? And this is just a "profile" that gets mapped onto the movement?
    Last edited by Darrel Taylor; - 28th January 2013 at 05:06.
    DT

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Hi Darrel,
    Thank you very much for spending time on this, I appreciate it!
    I guess +/-5 isn't TOO bad, always ending up short of target would be better than overshooting, then I could "creep" the position the last couple of counts but obviously ending up right on the spot was/is the goal.

    Is it supposed to be able to move to any target position? Not just a multiple of V_Max?
    Yes, absolutely. Any arbitrary position.

    Is it supposed to move from any position to any other position?
    Yes, absolutely. From one arbitrary position to another, in both directions. But I guess you can think the profile generator as moving from 0 to any position by simply taking the "output-position" of the profile generator and add that to the actual position variable. Ie the profile generator creates a relative position output which is then added to the real position variable. Hope that makes sense.

    Or is that part handled in your routines? And this is just a "profile" that gets mapped onto the movement?
    Not sure I understand, or perhaps the answer to the previous question covers it (reading it again I think it did)....
    Anyway, the feedback loop moves the motor to whatever position is put in the Position variable. But I need to "move" the target position at a speed that the motor and load can follow in real life. Simply stepping the position variable +/-12345 counts (or whatever) is very hard on the motor and for the PID-loop to handle without overshooting etc. It can be handled by de-tuning the filter to less than optimal response but who wants that.

    The best way to move from one position to another is to "move" the target position at a pace that the motor can actually follow. Ie ramp it up, keep at speed, ramp it down. Or, if the move is short, ramp up and at half the distance ramp down. Ideally it should be done with a 3rd order motion profile to reduce the jerk at the beginning and end of the acceleration phase. Ie you're not only ramping up/down the velocity but your also ramping up/down the acceleration creating an S-curved velocity profile instead of one with linear "sloped". But like I said, the 2nd order one proved hard enough.

    Again, thanks!

    /Henrik.

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    >Thank you very much for spending time on this, I appreciate it!
    You help everyone out too, it's nice to be able to do something for you for a change.

    Thanks for the explanations, now I have a better understanding of what it needs to do.

    Although the idea of just splitting the profile in half and doing the exact same thing in reverse for the second half was interesting ... that's what's causing it to only move to multiples of V_Max. I need to change that.

    And I need to make it go both directions, it only goes forward right now.

    I hope to have something by the time you wake up in the morning.
    Sometimes being on the other side of the planet is helpful.
    DT

  7. #7
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    henrik how does this look ?
    can the pid routine take byte sized increments
    Attached Files Attached Files

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Richard,
    Slow down, I can't keep up at the moment! ;-)

    The PID routine works with the error between the desired motor position and the actual motor position, the error magnitude it's able to handle depends on how aggressively it's tuned. Ie with low gain it'll handle large errors without overflowing the internal registers, with high gains it won't be able to handle an equally large error. But generally speaking yes, it'll handle an error of 255 without problems.

    If the PID is executed 1000 times per second "stepping it" 255 counts each tick would equal a velocity of 255000 encoder counts per second. Using a 500 line encoder that equals a velocity of 7650rpm, pretty decent.

    Looking at the code in your latest post I can't seem to see where you specify the distance to be moved.... (?) But that says more about my abillity to read others code than anything else :-)

    I appreciate your ideas very much but at this time I don't see how precalculating the move is going to work in real life. One move might last 100ms while another 100s. One move might travel 25 counts while another might travel 100000 counts.

    An example:
    I'm at position 0.
    * I want to go to position 4690
    * I want the velocity to be 123 counts per tick
    * I want the acceleration to be 8 counts/tick/tick

    Code:
    Tick	Accel	Vel	Pos	
    1	8	8	0	
    2	8	16	8	
    3	8	24	24	
    4	8	32	48	
    5	8	40	80	
    6	8	48	120	
    7	8	56	168	
    8	8	64	224	
    9	8	72	288	
    10	8	80	360	
    11	8	88	440	
    12	8	96	528	
    13	8	104	624	
    14	8	112	728	
    15	8	120	840	
    16	3	123	960	<---Velocity clamped at 123
    At tick 16 increasing the velocity by the set acceleration would violate the set velocity so the velocity is clamped at that point. No problems with that or the code to do it.
    At this point I know that it took 16 ticks and a total distance of 960 counts to get up to speed. So all that is needed is to start decelerating 960 counts from the desired target position, ie at position 4690-960=3730.

    The problem is that when moving at 123 counts/tick the target position will never be exactly 3730 at a specific tick. It'll be either 3675 at tick 38 and 3798 at tick 39:
    Code:
    Tick	Accel	Vel	Pos
    17	0	123	1083	
    18	0	123	1206	
    19	0	123	1329	
    20	0	123	1452	
    21	0	123	1575	
    22	0	123	1698	
    23	0	123	1821	
    24	0	123	1944	
    25	0	123	2067	
    26	0	123	2190	
    27	0	123	2313	
    28	0	123	2436	
    29	0	123	2559	
    30	0	132	2682	
    31	0	123	2814	
    32	0	123	2937	
    33	0	123	3060	
    34	0	123	3183	
    35	0	123	3306	
    36	0	123	3429	
    37	0	123	3552	
    38	0	123	3675	<---Should I start here?
    39		123	3798	<---Or should I start here?
    So, if I start decelerating (8 counts/tick/tick) at position 3675 I end up short. If start accelerating (8 counts/tick/tick) at position 3798 I end up overshooting - that's the issue with this.

    What I'm currently doing in my code is detecting when the distance to target is equal to or less than the distance traveled during the acceleration phase (that would be at tick 39 above) and then recalculate the needed acceleration (deceleration) in order to end up at target. That, however, isn't a one shot kind of thing since the needed acceleration (deceleration) might be 8.324 counts/tick/tick which obviously won't work with PBP. So, next tick I recalculate again and again and again - all the way to the end. The acceleration (deceleration) will toggle between 8 and 9, something like 8,8,8,8,9,8,8,8,9,8,8,8,8,9 - perhaps.

    This seems to work in simulation, I have yet to try it on real hardware. The drawback of course is it takes a lot processing power due the division involved in the math.

    The above numbers are just an example. The desired acceleration can be "any" number, the desired velocity can be "any" number and distance to move can be anything between 0 and several million counts. And they can change from one move to another.

    Thanks Richard!

    /Henrik.

  9. #9
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,123


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    If you are, as in your example, between tick 38 and 39, you are almost on target position.

    Why not change acceleration to 1 count/tick/tick sinc the drop in speed will not be noticed and you will get the exact steps you need?

    I am not an expert on this, just droped my idea.

    Ioannis

  10. #10
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    henrik
    did you ever get this working ?
    I have been messing with this for years and think I have finally worked it out . my solution is in C code but the idea is probably fairly portable if your interested

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Hi Richard,
    I have been working on it on and off but have yet to actually try it on real hardware. It's been over 6 months since I last looked at the code but the way I left it was that it figured out when it needed to start decelerating (which could be up to VMax past the ideal position) and then recalculating the needed deceleration value each tick untill ending up at the target. Basically this aproach WILL cause the decleration to be "steeper" than the acceleration which I know I said I don't want but in reallity I don't Think it'll matter that much, I mean, in simulation where a "move" is 100 "ticks" in total it looks "brutal" but in reallity I don't Think it'll be that bad.

    I have NO idea why you write in C (just kidding) but I'd love to see your code, thanks for offering!

    /Henrik.

  12. #12
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    my basic premise is that the input to the pid filter is velocity error (not position error) . the required velocity (setpoint) is found from a lookup tables who's in put is based on position . The move routine has 5 possible modes 4 is start a new move , 3 accelerate ,2 steady speed (cruise) ,1 decelerate, 0 in position , -1 stalled (failure).
    The lookup table was developed by - getting motor running at various velocities and throwing the brakes on (l393d style) and measuring the number of ticks travelled till at rest ,
    I plotted these in a spread sheet (the motor I'm using is a 171:1 gear motor 564 ticks per rev, target vel is 32 rpm ) interestingly the pos vs vel curve is ver nearly parabolic.
    the clever bit is using two lookup tables "the multi_map function" to interpolate the best velocity for the current position using only 9 entries in each table
    Attached Files Attached Files

  13. #13
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    some debug runs
    Attached Files Attached Files

  14. #14
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    beginning to think this may never fly in pbp
    I can get various versions to work in C using integer math , but with a real servo motor with 2000 counts /rev the numbers get out of control.
    although it seems to be workable using a 16f1825 @32mhz using C with floats.
    however using toy servos like the polou gearmotors at modest speeds and a nice faulhaber (probably not a toy ) I found on ebay its probably doable in pbp certainly works with C integer math even limited to 16 bit vars
    the pid refresh rate is critical nothing less than 10ms will work for real servos, up to 100ms can work for the others
    I have attached a xlsm spread sheet to show lookup table ideas
    Attached Files Attached Files
    Last edited by richard; - 6th September 2014 at 08:44. Reason: convert to english

  15. #15
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    funny I have been wondering why I can get this stuff to work on a atmega328 @16mkz clk without too much trouble , but with a pic18f45k40 @64mhz clk the performance is patchy
    then I found this link
    http://www.t4f.org/articles/optimiza...-and-pro-mode/
    i'm staggered it's as if microchip don't want hobbyists to use their products
    what amateur wants to pay $995 us for a complier ,why even have a free option that's so badly compromised
    I'm considering changing camp to atmel

  16. #16
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    henrik

    best I have come up with is assuming your time intervals are constant :-
    distance is the lessor of (normal full accel ramp ) or travel /2
    max velocity is the lessor of sqr( 2*accel*distance/2) or vmax

    next position = (current velocity + accel/2)+current position .
    while pos+next position<= dist/2 . from then on either constant v or decelerate mode
    I'm assuming pid routine can limit vel to vmax

    question here is what to do with the error and what is the error is it failure to reach next position or failure to achieve target velocity ?.

    it must fit into a lookup table somehow that way you could compensate for errors

    still thinking

  17. #17
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Hi Richard,
    Sorry for the late reply, been a bit busy here.
    I thought about commenting on the issue with C compilers and the whole AVR vs PIC etc but I don't write code in C and I don't use AVRs so I simply won't.

    I don't think the aproach with a lookup table for velocity is the way to go in my particular case. I can see it working in a specific application where you can tweak its value etc but what I want is a general purpose routine. I'm just starting to get back into this, setting up a small testbed with a little servo motor, 500 line encoder and LMD18200 H-bridge driver chip.

    My aproach, as it currently stands is based on around a basic state machine with four states - Stopped, accelerating, traversing, decelerating. Timing is very consistent, being interrupt driven, calls to the PID routine is currently at 1000-2500Hz (user selectable) but I think I need to allow a divisor between it and the profile generator.Basically, here's how it works:

    I've got:
    [Desired velocity] <- Set by user
    [Desired position] <- Set by user
    [Desired acceleration] <- Set by user

    [Output velocity]
    [Output position]
    [Output acceleration]

    On the very first call to the state machine when a new move is about to begin variables are initialized and [Desired position] is recalculated into a relative distance from the current position of the motor.

    In the acceleration state [Output velocity] is increased by [Desired acceleration]. Then [Output position] is increased or decreased by [Output velocity].
    If [Output velocity] is equal to or larger than [Desired velocity] it's clamped (before manipulating [Output position] ), the traveled distance is stored and the state is changed to traversing.
    If [Output position] is equal to or larger than [Desired position] / 2 the state is changed to decelerate.

    In the traversing state [Output position] is increased or decreased by the set velocity. If the output position is equal to or less than [Desired position] - "distance traveled during acceleration" state is changed to decelerate.

    In the deceleration state the [Output acceleration] is recalculated each tick based on [Output acceleration] = [Output velocity] ^ 2 / 2d where d is the distance left to target. [Output acceleration] is subtracted from [Output velocity] which is added to or subtracted from [Output position].

    Now, this will, most of the time, violate [Desired acceleration] when decelerating which I initially said was unacceptable. However, given the fact that the motor position is commanded and sampled at discrete time intervals and is allowed to move an arbitrary amount of counts (any velocity) I simple can't see a way to make it accelerate/decelerate with set rate, run at speed and end up at exactly the desired position - all at once. It's not perfect but just like timmers said early on the deceleration will likely be stretched out over hundreds or even thousands of ticks so in real life it might not even be noticable.

    Now I just need to get that little testbed up and running....

    /Henrik.

  18. #18
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    I have noticed another problem with my methods ,in that I'm calculating velocity by subtracting pos from old postion in the pid loop. when under acceleration this is actually average velocity not the actual (final)
    velocity . I have not been successful in determining velocity without impinging on pid evaluation time.
    using floating point routines with a 8bit cpu the highest pid rate I can achieve is 250 hz so average velocity is not good enough. might mean fp pid is not worth pursuing
    general purpose might be a tall order . I have a leadshine dcs303 digital dc servo driver , it runs a dcm50202 servo motor / 500line en with no problems (can achieve 3000 rpm and move to pos +- 1 count) . It will not even come close to achieving servo lock on the other motors I'm using. my other motors have a really high inertia this makes them more predictable for my "slow" routines providing you don't try to exceed their accel profiles. the low inertia servo is problematic

  19. #19
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,123


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    I am not an expert on this subject but would try to help. Is it necessary to use the PID routine all the time?

    Why not just call it just before the target point is close so that it will be used less and everything will be running much faster?

    Maybe I am away from what is discussed here... Just a thought.

    Ioannis

  20. #20
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Richard,
    Yes, I think floating point is going to take too much resources and I'm not sure it'll actually solve anything. The position is still "set" and sampled at discrete intervals, there's no way to force it to "hit" a specific position at a discrete interval while still allowing "any" velocity and "any" acceleration. If target position is NOT to be violated then something else will have to give. Either change velocity so deceleration can start at exactly the correct spot. Or change deceleration so the position will end up at the correct spot once velocity reaches zero. I'm opting for the second....

    I have successfully used my PID code with step and direction input running a motor with a 3600 line encoder at 4000rpm (960kHz step frequency), it'll position to 1 count without problem. The PID is executed at 1500Hz with processing power to spare. Here it is: ,

    for more details see my webpage. But it's being commanded by an external motion control software which is what generates the motion profile. The DCS303 manual mentions built in motion controller for self thest with trapezoidal velocity profile which is exactly what I'm trying to achieve. Unfortunately the DCS303 manual doesn't say much about how its profile generator works and/or which set parameters it may "violate" (if any) to achieve its goal.

    Ioannis,
    YMMV of course but in my case I'd say yes, it's neccesary. It's not just a matter of moving from point A to B as fast as possible, I want the motor to move from point A to point B following the profile generated by the code discussed here as closely as possible. Without the closed loop in there the motor could potentionally stall in the middle of the move.

    Fun stuff this....

    /Henrik.

  21. #21
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    henrik
    will this profile generator acutally "control" the motor or just output pulses/dir to another step /dir controller ?
    I'm thinking in the later case you have would heaps of time to do the sums and design a profile and then just output the pulses when prepared.
    to accelerate just decrement/increment the pulse interval by a fixed amount , the first and last few pulses and maybe even the transition to constant velocity could all be given special treatment. that treatment would need to be customised for motor/load/inertia as would max velocity and acceleration. bit like mach3 in a pic ?

  22. #22
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,610


    Did you find this post helpful? Yes | No

    Default Re: Motion profile generator.

    Hi Richard,

    The profile generator will generate the moving target setpoint that the PID filter servos the motor to, output of PID filter goes to PCPWM module which drives the H-bridge. Everything running on the same PIC. (Step/dir signals could also provide the moving target setpoint TO the PID filter (bypassing the profile generator) but for this project I'm not interested in generating step/dir signals.)

    I think that generating a step/dir based profile would actually be easier (though generating step pulses at any decent frequency isn't easy on a PIC) because then you are basically controlling the motor down to the individual step level. For each "tick" you either issue a step or you don't so it's easy to "hit" the exact spot where deceleration needs to start in order to get to the target position without violating any of the settings.

    When doing the profile generation, PID, PWM and feedback in the same PIC it's not as easy since the motor is moving more than a single count for each "tick". You tell the motor to move an arbitrary amount of counts per "tick" which so you're likely to overshoot the "sweetspot" where you need to start decelerating.

    I hope that makes sense.

    /Henrik.

Similar Threads

  1. Motion Capturing
    By koossa in forum Off Topic
    Replies: 0
    Last Post: - 30th June 2009, 11:05
  2. Suggest a motion sensor Please
    By sougata in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 4th March 2007, 13:22
  3. Wireless Motion Sensors.
    By koossa in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 17th October 2006, 21:57
  4. Need low Profile LCDs
    By Foxx373 in forum General
    Replies: 8
    Last Post: - 26th October 2005, 17:33
  5. Motion Tracking
    By JEC in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 5th November 2004, 00:58

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts