# Thread: PIC-Based Step Generation With Linear Acceleration?

1. James,

The only place the typo "D" appears is in the decision box "D =< A" and in the "yes" branch from that box reading "OUT <- D". They should read "DN =< A" and "OUT <- DN". Everywhere else, assume the character is "0", not "D". I'm sorry I posted such a poor resolution flowchart gif.

Distance To Go was named DN (DowN) because it is always subtracted from, causing its value to decrease or go down. Go figure; it's not real descriptive but it's what I chose to call it when I generated the flowchart. At all times it represents the distance left to go.

UP is the distance moved while accelerating. The UP value 'freezes' when acceleration ceases. DN is compared against UP; the deceleration state begins when DN < UP.

Mariss

2. Mariss, the flowchart you provided... confuses the heck out of me. I think I can see how it could calculate velocity... but it seems /really/ over complicated for that... can you give me a little more detail about what the OUT = D or OUT = V or OUT = R commands actually do? Is that just a way of saying that it is returning the Distance to go or Velocity, or Remainder at that point? Or is that saying that the stepper should move forward that many steps at the current velocity?

In the mean time, I've done some trouble shooting and simulation on my code, which, of course, seems much simpler to me; but isn't that always the way of it? LOL...

https://docs.google.com/document/d/1...y4/edit?hl=en#

It's now producing very (very) simple output that seems to be correct to me. For example, in the case that X is the axis with the largest movement, and it is going from an initial position of 0,0,0 to 10,5,2, it produces a table like the following, where:

i = distance to go

sd = stopping distance, I thought this was going to be related to acceleration, but it seems to be working out to just be half of the distance to travel, so I'll probably change the way it is calculated.

xp,yp,zp = the positions of the three axis

xv = X Velocity, expressed as mS to wait between steps. At this point, these are just test values... working values would depend on the motors, hardware, etc...
ma = Maximum Acceleration, expressed as the number of mS to increase or decrease the delay between steps.

Code:
i	sd	xp	yp	zp	xv	ma
10	0	0	0	0	200	20
9	1	1	0	0	180	40
8	2	2	1	0	140	60
7	3	3	1	1	 80	40
6	4	4	2	1	 40	20
5	5	5	2	1	 20	0
4	5	6	3	1	 20	20
3	5	7	3	1	 40	40
2	5	8	4	2	 80	60
1	5	9	4	2	140	40
0	5	10	5	2	180	20
So you can see that the velocity is changed appropriately and the acceleration is nice and... curvy... with RAMP_ACCELERATION commented out, it does this:

Code:
i	sd	xp	yp	zp	xv	ma
10	0	0	0	0	200	20
9	1	1	0	0	180	20
8	2	2	1	0	160	20
7	3	3	1	1	140	20
6	4	4	2	1	120	20
5	5	5	2	1	100	20
4	5	6	3	1	120	20
3	5	7	3	1	140	20
2	5	8	4	2	160	20
1	5	9	4	2	180	20
0	5	10	5	2	200	20
Probably need to define ma as more than 20 in that mode...

I need to test further with longer and shorter movements, different values for the xv and ma (and sv = Starting velocity) parameters and then make it manage movements where the Y or Z axis is the largest movement.

It compiles to 722 words without ramp and 855 with ramping on a PIC 16F690 using the free HiTech C compiler. That is less than 20% of the code space, so adding a minimal parser to accept some sort of commands to send way-points and max velocities / accelerations shouldn't be impossible even on that little chip.

I'd really love to hear some feedback...

3. Lot's of debugging on the code at:
https://docs.google.com/document/d/1...y4/edit?hl=en#

I've added a printf to make it easy to capture the result for debugging.

Here is a nice sample output for a move from (20,5,0) to (100,50,2). Remember:

Vel=Velocity, expressed as mS to wait between steps. At this point, these are just test values... working values would depend on the motors, hardware, etc...

Acc = Acceleration, expressed as the number of mS to increase or decrease the delay between steps.

Code:
step:stop	x	y	z	vel	acc
0080:0001	21	6	0	790	20
0079:0002	22	6	0	770	30
0078:0003	23	7	0	740	40
0077:0004	24	7	0	700	50
0076:0005	25	8	0	650	60
0075:0006	26	8	0	590	70
0074:0007	27	9	0	520	80
0073:0008	28	9	0	440	90
0072:0009	29	10	0	350	80
0071:0010	30	11	0	270	70
0070:0011	31	11	0	200	60
0069:0012	32	12	0	140	50
0068:0013	33	12	0	90	40
0067:0014	34	13	0	50	30
0066:0015	35	13	0	20	20
0065:0015	36	14	0	20	20

<snip boring stuff in the middle at max velocity, trust me, z did right>

0017:0015	84	41	2	20	20
0016:0015	85	42	2	20	20
0015:0015	86	42	2	40	30
0014:0015	87	43	2	70	40
0013:0015	88	43	2	110	50
0012:0015	89	44	2	160	60
0011:0015	90	44	2	220	70
0010:0015	91	45	2	290	80
0009:0015	92	45	2	370	90
0008:0015	93	46	2	460	80
0007:0015	94	47	2	540	70
0006:0015	95	47	2	610	60
0005:0015	96	48	2	670	50
0004:0015	97	48	2	720	40
0003:0015	98	49	2	760	30
0002:0015	99	49	2	790	20
0001:0015	100	50	2	810	10
Probably lots more bugs to find... sure would love some help...

Found a link to a simple G code interpreter... and a motion planner that would do what my code does (actually looks a LOT like my code! LOL) but doesn't do ramping. I hope to incorporate the G code part soon.

4. You are doing a great job, and I would have loved to help... but I only do assembly, and I'm working on my own project with my own goals, so I would not be much help.

Hope you get some help soon

5. I'm a bit lost as to what your code is for James.

Are you pre-generating a table for every move, then using the table for step generation in real time while the move is occuring? What's it for?

Also how are you handling fractional interpolation (ramp amounts less than 1 step)?

6. @Roman, tables use memory space that isn't available in little PICs. I'm generating the /steps/ and the /delay/ between steps on the fly. And in this case, I think the calculations are easy enough that using a table is completely unnecessary in all cases. The printout "table" is just a debugging aid showing what the result of those "on the fly" calculations turned out to be for a specified move. This is the exact same thing your table based path planner code is doing, but without the tables. So... if you look at the sample above, for the move from (20,5,0) to (100,50,2), a step pulse is sent to each axis when the axis position number changes... that is: After each step on the X axis, more or less every other step for the Y axis, and just twice during the move for the Z axis. The "Vel" column shows how much time delay there is between each X axis step. So there is generally twice that delay for each Y axis step, and so on. The "Acc" column is showing how much Vel will change on the next cycle. It is there only to make the acceleration change obvious.

You should NOT need a google account or anything else to view the actual code; I've set it to be fully public to the web. Please click on:

https://docs.google.com/document/d/1...y4/edit?hl=en#
and tell me what you see?

7. I clicked the link, then saved a screenshot for you. I believe it's requiring a google account, the ********. Google are the new evil empire. You probably have a google account that auto-cookies so you never see this screen...

Ok, re the tables I get what you are doing, its the same basic process (and standard process!) that I used on my PIC CNC machine controller. The ramp tables and such we recently discussed in the other thread is for my new PNP controller.

You are doing the process right but there are a couple of problems. One is the fractional linear interpolation. Let's say you need to move from x0 y0 to x100 y34. Your PIC does the math x/y = 100/34 = 2.94117 so it *should* do a y step after every 2.94117 x steps. But it will probably round that down to 2. That's 2 x steps for each y step.

So now instead of doing a straight line from 0,0 to 100,34 it does a short diagonal line from 0,0 to 68,34 then a straight line from 68,34 to 100,34 to finish the move. Very nasty. The common solution is to use large floating point numbers in real time which is the reason Mariss uses a big fast FPGA chip for the step pulse generation.

The second problem of course is speed. If you are using a stepper driver like the Linistepper at 3600 steps/rev or most stepper chips at 3200 steps/rev and you need a typical (low performance) top speed of about 10 revs/sec you need to be able to generate >32000 steps per second.

With a PIC 16F and max of 5 MIPs that gives you 5000000/32000 or 156 PIC instructions to calculate floating point interpolation on at least 2 axes, generate maybe 3 step pulses on the port and clear the port (to make both / and \ edges of the step pulses) do the correct timing and testing the timer, sequence your next time value into the queue, check for reached the decel point, check for reached end of travel, possibly check for limit switches, panic stop button, new move commands etc...

And this is only for a relatively low performance machine up to 10 RPS. My PNP machine needs 25 RPS not 10 and many people on the forum use more than 25 RPS.

Another complexity is the velocity control, like the interpolation this is fairly critical to move the machine at the exact speed. Mariss says above he uses a 16bit velocity value, and I use a 24bit value (not to be better but because of the way my math code works). Either way your PIC code has to interpret all the velocity accel ramp values for every stage of the accel ramp, which may involve a further 16bit/24bit/float calculation for each ramp step done on the fly every mS (or however long your ramp steps are) or to pre-generate all the 16bit/24bit/float timing values for every ramp step first, then load them from RAM as your accel is done.

You can get some success with 3D accel ramps at *very low* step rates even on a small PIC, but it's not a trivial task do do this at the real world speeds needed. There's a reason Mariss uses a super fast FPGA for the step timing generation and a PIC24 for the control math, and that I needed a PIC18 at 10 MIPS and still had to strip everything right to the bone, code chunks in assembler for speed and pull some very nifty math and timing tricks out of my hat to get the PIC18 to barely cope with the task...

But please don't let me put you off.

8. Ok, I've placed the code at:
Firmware / Embedded Microcontroller based Computer Numerical Control

Notice there is NO floating point.... not even any real multiplication or division.

Bresnehan removes the need for floating point maths and still manages the messy slopes of the secondary axis. The PIC need do only additions and subtractions which it can do in a very timely manner up to even 32 bits. I'm currently doing 16 bits and I believe the codes should be able to outpace any motor system.

9. RomanLini, you should look up the bresenhams routine for linear moves.

And floating point for this is overkill by far! I have a working routine made entirely with integer math, and it does not have to deal with approximations at all.

I briefly touched floating point on my hunt for a good routine, and I dumped it shortly after.

You don't need any tables for this.

10. Noticed a little problem you might have there James. If the 2 axis moving have a different accel profile, you might end up with the slave axis accelerating too fast.

Lets say you want to move X: 50 and Y: 49. Almost every step on X results in a step on Y. But if Y has half the acceleration (in setup) of the X, you will end up with an axis thats moving faster than it should. I solved this by calculating velocity for all axis at the same time.

If all axis have to be identical, then this should not be a problem.

I have started looking into the code now. I can understand most of it, but I can't write anything.

11. Absolutely right, but it can be managed either by running all at the acceleration of the slowest, a or by checking and setting Max to slowest for each run.

12. You will have to do a calculation if the slowest is the right one to use. You can't say that you will have to use the slowest for every time. This will be a problem for moves where the master axis is much longer than the slave axis.

When you have determined what axis is the best to use, this wont be a problem for linear accel, and decel.

Page 3 of 12 First 123456 ... Last

#### LinkBacks (?)

1. ###### Building a Cheap DIY CNC Machine (1st attempt) - FoxyTronics
Refback This thread
06-08-2013, 09:50 AM
2. ###### How to generate a PWM with varying frequency?
Refback This thread
03-15-2013, 10:32 AM
3. ###### Generating a linear delay from min to max.
Refback This thread
05-21-2012, 10:22 PM
4. ###### Generating a linear delay from min to max.
Refback This thread
05-10-2012, 11:21 AM

### About CNCzone.com

We are the largest and most active discussion forum from DIY CNC Machines to the Cad/Cam software to run them. The site is 100% free to join and use, so join today!

### Follow us on

Search Engine Friendly URLs by vBSEO ©2011, Crawlability, Inc.