Shop OBEX P1 Docs P2 Docs Learn Events
Ken Bash's 6-axis CNC Code (as discussed in the P2 Live Forum) — Parallax Forums

Ken Bash's 6-axis CNC Code (as discussed in the P2 Live Forum)

Hello all,

If you attended JonnyMac's Spin2 for Beginners Series - Stepper Motors, then you also met Ken Bash. Ken spent a number of years planning to use the P2 in a six-axis CNC controller. Ken's desire is to see the code be used by others, in keeping with the MIT license, which I've put onto his code. This code is offered unsupported by Ken Bash or Parallax, entirely as is, to see if it could be the basis for a CNC application.

Thank you @KenBash for your generosity and explanation about how this works.

Without further ado, I present to you Ken's source code and his letter to me (paraphrased in parts). . .

Sincerely,

Ken Gracey

=================================================

Dear Ken,

Attached is my 6 axis CNC code for the P2. I'm sending it directly to you because I've decided to open it up
to the community and I think you might be the best judge of how to keep it that way.

. . . .details about how it works follow. . . .

I never got a 100% understanding of the P2 LUT memory sharing between two adjacent cogs, but my goal
was to have this shared Ram used for one cog ( the “Setup Cog” or SCog) to per-calculating moves and put
that data into a shared memory block that a second cog (the “Movement Cog”, MCog) uses to do the
move. While that move is in process, the SCog takes the INTENDED “TO” position of each subsequent
move and pre-calculates and puts the next step/direction information that the MCog will use into memory.

The MCog would be delayed between move segments only the time it takes to switch a pointer to the next movement data block. This would be done in some sort of circular (Ring) buffer fashion.
I had the code ALMOST working with shared LUT memory in one version but it kept “Breaking” and I
couldn't figure out how to fix it. I think this version just uses the hub ram to pass values.

This preliminary P2 code isn't divided for two cogs yet. It is however doing the setup and the move in two
distinct program blocks and should be fairly easy to break into multi-cog functions for ultra high
precision/speed machines that might actually need it.

This method would also allow this movement data to be per-calculated and streamed into the Ring buffer
from an external source ( similar to a slicer generating Gcode for a 3D printer) opening up the possibility for an outside program to do compensations for machine “Slop” or insert other functions ( like firing a laser for 3D metal printing ).

Another improvement I intended to make was to have each step trigger on an external clock signal instead of using a delay like I use here. This would allow the over-all machine speed to be completely jitter free and managed by an external pulse signal or cog adjusting the speed relative to some external stimulus.

For now:

The SCog takes the current AT position for all 6 axis and calculates all the movement particulars ( steps,
direction, etc) for 6 axis TO positions and shoves it into a memory block ready for another section of code
that does the actual move. ( At 180mhz, I think I was getting something like 20,000,000 steps per second,
at top speed. This gives you 1 micron resolution at roughly 45 mph )

My P1 code has everything stuffed into one cog. You send it a 6 axis position to move, set the “go” flag and it calculates all the steps for each axis, makes the move then resets the flag to tell the calling program it's ready for another move. I never measured how much time the calculations took, because the delay never affected the machines I needed to move. However, for the “Grand daddy” of machine control, you may want incredibly fast motion and incredibly high resolution with little or no “Jitter” in the pulse output.
Assuming that you just “homed” all 6 axis, ( I call them X,Y,Z,W,R,T ) the current positions are all 0.
a high level command of GO( 1000, 300, 68, 500,1000, 423) (for instance) takes the current position of
each axis, calculates the number of steps needed to get to where you want to go, figures out which axis is
the largest axis and uses that axis as the base count for the move.

The only “Tricksy” part of my code was to figure out which axis is the “base” axis and set the ratios of the
other axis to that base value. Instead of having to do some sort of fancy math, all I do is left shift the bits of every step count until I get a 1 in the highest bit position. This automatically makes it so that the ratios of the other 5 axis are correct. This value becomes the “Step Add” value for each axis. This ratio value is
added to an accumulator for each axis each time the base axis takes a step. When there is an overflow, it's time for that axis to take a step. A port is set high to start the pulse, the current “AT” position is incremented or decremented according to which direction a motor is moving, then the port is reset to low triggering whatever kind of drive is hooked up to the port.

It's easier to see if you use binary so for instance: GO (64, 0, 16, 32, 64, 1)
these values are left shifted to become step rates of:

10000000000000000000000000000000 (x)
00000000000000000000000000000000 (y)
00100000000000000000000000000000 (z)
01000000000000000000000000000000 (w)
10000000000000000000000000000000 (r)
00000010000000000000000000000000 (t)

Y never moves because there is never an overflow. W steps every other time X steps, Z steps every forth
time X steps and so on. ( this method works fine when the step sizes are other than powers of 2, this is just an example ) you take a step for an axis each time you add that axis steps size to its current value and there is an overflow. ( I think this “step on carry” limits the step rate to every other time through the loop, but might also work by stepping any time there is a bit in the highest position to double the maximum speed ).

Since it is possible for a slower axis to be at a fractional position and one step off the intended “GO”
position when the base axis is finished moving, the move function needs to keep going until all axis are in
fact at the intended “GO” position. THIS IS NOT the case in this preliminary code. Since all the calculations
are being done from the actual AT positions when a move is finished, this didn't make any real difference if one axis was a step off or not ( for my machines ) .

However, on a future system that is using the INTENDED “GO” position to pre calculate the next move
before the last move is done, a system will rapidly get off position through a series of partial moves. This
current MOVE loop needs to be modified so that it continues until all 6 AT positions are equal to their TO
positions.

The intended future direction for this code was to:

  1. Have one cog doing all the initializing stuff like HOME all axis, set software boundaries, Load G-code files, etc.
  2. A second cog would be the SCog doing movement setup from GO commands or streaming data into the shared Mcog memory from an external source.
  3. The third (Mcog) would do the movement stepping. ( depending on the actual speeds necessary and acceptable setup delay between moves, these functions may or may not need to be divided into different cogs but should be kept modular to let this be a possibility. For now, everything fits into one cog and can easily run this way if the delay time of calculating everything is not an issue. I suspect that most machines will actually move orders of magnitude slower than what the code can produce. If the stepping function is modified to wait for a clocked trigger, this will smooth out any jitter and will make a pretty good single cog control routine. This external clock trigger is also how the software can be synchronized with things like a lathe for software gearing of an XY tool-post or spindle head. )

Now... here's where it gets fun:

If you let the Mcog do the movement function without actually physically controlling any output ports, it is
in effect doing a perfect “Virtual” move with the AT positions in memory changing to where an axis
SHOULD be from moment to moment. Share these At positions in Hub ram and:

  1. A forth (fifth, sixth, etc) cog could track these virtual positions and compare them to actual encoder
    positions generating an error signal for a DC motor drive. This final Drive cog (Dcog) might generate a
    different type of signal for every axis if desired. One axis might be a step and direction output, another a
    DC drive signal, another, a serial command to an intelligent motor drive, another, voltage values to direct
    drive transistors to microstep a linear motor or a hydraulic cylinder control valve. These axis would have the ability to feed back to the Mcog to stop motion or slow it down if an axis was starting to lag too far from its “Perfect” position OR a safety trigger was hit. They would also have the ability to easily NOT move an axis that was about to be beyond the physical limits of a machine but track and start moving again when that axis position was back into its acceptable motion range.

Another potential addition is of course using the Virtual position data in conjunction with the polar
coordinate functions to control not just linear machines like milling machines and 3D printers, but Polar
coordinate machines like robot arms as well.

If one cog is interpreting Gcode, and a few others are running motors, you still have cogs available to do
things like: temperature monitoring (bearings, electronics, etc,) machine wear tracking (to signal
adjustment/repair if “Slop” gets outside of limits or is increasing too rapidly,) and so on. The P2 was always the chip that was going to be the ultimate single chip motion controller. I hope someone can make it so.

Keep me in the loop if anyone wants to take this and run with it.

Take care Ken, I hope this helps the Parallax community a bit.
Ken Bash

Comments

  • cgraceycgracey Posts: 14,151

    I have been looking for some multi-axis platform on Amazon that we could all buy for maybe $150, so that we could experiment with this.

  • Cluso99Cluso99 Posts: 18,069

    The Creality Ender 3 is around $200 last time I looked. A P2 upgrade would be a nice addition. I have one and have been extremely happy so for anyone wanting to play with a P2 driver for this would be starting with a nice but cheap 3D printer. My son has one too, so I don’t think it’s luck.

  • cgraceycgracey Posts: 14,151

    @Cluso99 said:
    The Creality Ender 3 is around $200 last time I looked. A P2 upgrade would be a nice addition. I have one and have been extremely happy so for anyone wanting to play with a P2 driver for this would be starting with a nice but cheap 3D printer. My son has one too, so I don’t think it’s luck.

    Maybe that's what we need to use.

  • ErNaErNa Posts: 1,752
    edited 2021-03-16 23:51

    (Whoops! Erna, could you please repost the link. I was trying to discover it and I wrecked it. - Chip)

    That might be an alternative

  • Cluso99Cluso99 Posts: 18,069

    @ErNa
    That looks like a nice piece of kit too.

  • Wow Erna didn't realise those could be had that cheap. It doesn't add much to go for larger vs smaller sizes. It wouldn't be hard to add a 5th 'angle' axis for rotary engraving to that setup.

  • ErNaErNa Posts: 1,752

    Yes, I bought such a kit earlier, and it's complete. Plastic parts are 3d-printed, metal parts are copied designs, the board is working, limit switches I missed. It's okay to work with wood or foam, so just what to expect for the money. It's incredible how cheap you can produce working with robots, owning coal mines, chemical plants etc, even negotiating good delivery fees. ;-)

  • RaymanRayman Posts: 14,632

    Wonder why it's cheaper in Germany... Cheapest one I see on Amazon is ~$200.

    Looks like some use Grbl and Arduino: https://github.com/grbl/grbl/wiki/Using-Grbl

    I guess I'd see about compiling Grbl with FlexSpin C and then using the software on that page...

  • ErNaErNa Posts: 1,752

    we have no trade wars ongoing ?

  • My $0.02 (it was bound to happen) :| :

    • We are talking six axes
    • Why be another me-too cartesian machine solution?
    • Parallax focus is on robotics education

    https://anninrobotics.com/

  • cgraceycgracey Posts: 14,151

    @Mickster said:
    My $0.02 (it was bound to happen) :| :

    • We are talking six axes
    • Why be another me-too cartesian machine solution?
    • Parallax focus is on robotics education

    https://anninrobotics.com/

    That's a pretty neat arm. It looks like the whole kit would be over $1500, right?

    To really grease the skids, the mechanics of these systems need some gross simplification. All these compounded steppers accumulate quite a load.

    I am going to see if anyone has developed some closed-loop pneumatic arm. It could weigh much less and possibly be a lot less complicated.

  • TBH, I only priced the aluminum parts and that was around $600. The 3D printed solution might be a good way to go.

    Difficult to close a position loop with pneumatics; too bouncy.

  • @Mickster said:
    Difficult to close a position loop with pneumatics; too bouncy.

    I will cheerfully grant you difficult, but not impossible. Depends upon what coefficients you're willing to accept in your loop... S.

  • Hi Mickster,
    I think you missed the point of this code. It doesn't make any difference whether a robot is moving in cartesian mode or polar mode. If you have a bunch of motors that need to move in smooth, synchronized motion this is a method to make that happen.

    It doesn't matter whether you are moving to an XYZ position or moving a 6 axis robot arm to specific angles. Be they angles or cartesian positions, they are still delivered in the format of something like: "G 1000, 290, 5303, 882, 1000,0 " When it comes down to the brass tacks of movement, a group of motors is given a group of positions that they are supposed to move to and a "Low Level" function moves them to that position. This is that low level function.

    In fact, for most industrial machining systems, the movement code is usually for some combination of cartesian AND polar coordinate movements. For instance, a CNC lathe will have a tool post that moves in cartesian planes but it often must coordinate with the spindle rotation as well. A CNC milling machine will often have one or two rotational axis that must coordinate with the XYZ movement of the cutter and often the cutter itself can be angled to add the 6th axis of movement.

    The system that generates these "GO" commands (Gcode) is called a "post processor" and is usually specific to a particular machine design. This post processor software must know the particulars of a machine such as which axis are cartesian and which are polar. What gearing is on each axis? If you're using a cutter bit, How long the cutter is and what diameter it is are also part of the things the post-processor must know.

    A 3d slicer is a type of post processor. It generates different GCODE commands for the different types of 3D printers whether they are XYZ machines like the Ender series or some other odd combination like the Festo iFab 3d printer.

    This code 6 axis code wasn't intended to be the post processor. That's for better heads than mine to work out. However, It works fine for cartesian machines as-is, it can also be the basis for non-cartesian systems as well. I agree that fancy multi axis arms are much cooler than cartesian stuff, but when it comes down to the basics, all that fancy stuff still has to be told where to go and how to get there. If you have better code to do that, I'd love to see it.

  • I guess that my point is that; demonstrating 6 axes of coordinated motion from a single device is more interesting than 3. :)

  • @Scroungre said:

    @Mickster said:
    Difficult to close a position loop with pneumatics; too bouncy.

    I will cheerfully grant you difficult, but not impossible. Depends upon what coefficients you're willing to accept in your loop... S.

    True and the same can be said for substituting rubber bands for drive belts. :)

  • ErNaErNa Posts: 1,752
    edited 2021-03-18 17:28

    When it comes to multiple axes: https://motionsystems.eu/ And when it comes to CNC machining of many kinds, look here: https://grblgru.com/

  • ScroungreScroungre Posts: 161
    edited 2021-03-19 16:35

    Six axes also has the neat detail that you can (provided your machine can) do not only x,y, & z, but also pitch, yaw, and roll, allowing your "cutting head" to approach the material from anywhere at any angle. S.

    ETA PS: I've seen machines with 22 axes on them, and had a hand in building several with 12.

  • @cgracey said:

    @Mickster said:
    My $0.02 (it was bound to happen) :| :

    • We are talking six axes
    • Why be another me-too cartesian machine solution?
    • Parallax focus is on robotics education

    https://anninrobotics.com/

    That's a pretty neat arm. It looks like the whole kit would be over $1500, right?

    To really grease the skids, the mechanics of these systems need some gross simplification. All these compounded steppers accumulate quite a load.

    I am going to see if anyone has developed some closed-loop pneumatic arm. It could weigh much less and possibly be a lot less complicated.

    Here is a servo-driven arm which is very successful!
    https://hackaday.com/2021/03/19/robot-arm-achieves-amazing-accuracy-with-just-servos/

  • Hi

    Did you see what this guy did with his re-engineered servo's??? (related to the arm above)

    https://bitbucket.org/adamb3_14/servoproject/src/master/README.md

    Dave

  • @macrobeak
    @tritonium

    Wonderful 👍👍👍👍😎

    how to implement industrial strength control loops

    The dual-loop feedback system has been my forte since the early '90s
    Any other method is only about motor positioning...but it's the load that's important. Heck, though... CUI do some very inexpensive kit encoders but hats off to this guy for making his own.

    This is the most satisfying hobby robot video that I have seen because the motion is smooth and tight 👍

Sign In or Register to comment.