Shop OBEX P1 Docs P2 Docs Learn Events
CNC - I know it is scary, but I have been thinking! — Parallax Forums

CNC - I know it is scary, but I have been thinking!

Hello Everyone

Over the last several weeks, I have been thinking very heavily about the subject of CNC machines and 3D printers. As users of the Propeller, the biggest problem that confronts us, pertaining to these subjects, is usable code, unless of course, we want to write it all from scratch.

In the past, I made a very serious attempt to port Teacup, which is firmware for 3D printing applications, based upon the Arduino controllers. I suppose it is needless to say that I failed miserably, but it was not due to a lack of effort. Once again, I am in the same boat, but this time, my focus is upon the GRBL firmware for CNC machines, and it is also based upon Arduino.

I personally have always been a big fan of the Propeller, ever since I learned about it's existence, and I have always believed that it is a nice controller for various machines. Furthermore, I still believe this is true, but the possibilities are limited because the code base is very limited pertaining to machine control.

Without going into what I am building or what projects have been shoved to the back burner, I would like to focus this discussion on a solution to our limited machine control code base.

As mentioned, I made a previous attempt to port the Teacup firmware, but as of today, I came to the conclusion that I went about it totally the wrong way. The problem with porting Teacup, GRBL, or any other Arduino firmware, is their use of timers and interrupts. Instead of porting individual firmware, my focus should have been on porting and duplicating Arduino timer/interrupt behavior, right down to names, registers, etc...

If the timer/interrupts can be duplicated on the Propeller, to replicate the Arduino timers and interrupts, then we as a community, would have access to a much larger code base, but more specifically to a code base which supports machine control.

Before diving into this, I thought I would see what the gurus have to say about the plausibility of such an endeavor. I do not know if it would be possible with the Propeller architecture, but I think it should be possible.

What do you guys think? Am I off my rocker, or could I be onto something?

Comments

  • jmgjmg Posts: 15,148
    idbruce wrote: »
    .... but as of today, I came to the conclusion that I went about it totally the wrong way. The problem with porting Teacup, GRBL, or any other Arduino firmware, is their use of timers and interrupts. Instead of porting individual firmware, my focus should have been on porting and duplicating Arduino timer/interrupt behavior, right down to names, registers, etc...

    If the timer/interrupts can be duplicated on the Propeller, to replicate the Arduino timers and interrupts, then we as a community, would have access to a much larger code base, but more specifically to a code base which supports machine control.

    Before diving into this, I thought I would see what the gurus have to say about the plausibility of such an endeavor. I do not know if it would be possible with the Propeller architecture, but I think it should be possible.

    What do you guys think? Am I off my rocker, or could I be onto something?

    Hmm.... exact hardware emulation is going to be very difficult, so this is close to the 'off your rocker' end of the scale :)

    AVRs have more classic MCU timers, with prescalers, variable lengths, and PWM in hardware.
    A direct hardware action like overflow or input edge, can trigger a code vector (interrupt), usually done to assist the peripheral. hardware actions also set flags, that are later tested.
    None of that has a close equivalent in P1-land, so you would be always 'not quite equivalent', and it is the details that bite.

    Other possible approaches :
    a) Build an AVR peripheral disassembler, that reads a AVR HEX file and reports the ultimate timer features in a table.
    Use that information, to build equivalent Prop COG code.
    Here, rather than trying to clone registers, which is always going to fail, this tries to clone the functions as used.

    The plus side of this, is it is widely educational useful, and could take any working AVR project (for supported devices) and give a Prop equivalent framework.
    Think of it as an 'AVR-Prop Wizard'

    b) Accept partial defeat, and simply buy a small AVR, for use as a Peripheral.
    The prop then can use the config information it finds in your source.
    Of course, this will not respond quite as quickly to an interrupt, and one COG would be tasked with the software layer of P1-Land to AVR-land linking.
    To compensate for the slower P1-AVR link, you could choose a 'better avr', that has more chance of peripherals needing less interrupt support.

    Possible 'better avr' candidates could be :
    ATTINY817-MFR Microchip Technology Inc 20MHz 8KB QFN24 Ind 125C Green T&R 0 1000 $0.6900
    ATTINY1617-MFR Microchip Technology Inc 20MHz QFN High Grade (125C) Green 0 1000 $0.7100

    This post on AVR site shows the family, looks to span 2k to 32k

    http://packs.download.atmel.com/#collapse-Atmel-ATtiny-DFP-pdsc
    ...
    1.2.118 Added support for ATtiny3217, ATtiny3216, ATtiny3214, ATtiny1617, ATtiny1616, ATtiny1614, ATtiny416, ATtiny414, ATtiny412, ATtiny214 and ATtiny212.
    The 32KB tinyX will fill-out the flash part of the unified memory.
    The 2KB tinyX might be for growth from a tiny102 and tiny104.


  • MJBMJB Posts: 1,235
    edited 2017-03-26 13:24
    @idbruce
    what stayed in my mind from your various threads about 3d printing and CNC and porting Arduino SW I have the impression you are struggling with finding the right/appropriate level of abstraction.
    I mean from reading in a G-Code file, generating the waypoints, then the motion profiles, n-steps in direction, down to the driving the phases of the steppers ...
    The upper algorithmic layers of those are not really hw dependent if written in C.
    But eventually you come down to where you have pins to wiggle in realtime.

    Trying to emulate an AVR architecture on the Prop I think is not a good approach.
    This needs to be made in a way that fits the Prop architecture to provide the functionality you need in a Prop way.
    Kind of a HAL
    You can even split those functions in seperate COGs/Threads what an AVR can not.

    As often this looks like needing a divide and conquer approach,
    or 'how do you eat an Elephant? - bit by bit'
    just my 2c ;-)
  • Well guys, that is not what I wanted to hear :) but thanks for your input anyway.
  • The only module I recall having really scary hardware dependencies was the stepper module. That one uses interrupts and hardware knowledge pretty heavily to get the required performance from the AVR chip. Planner, which is where the really hairy work is done, isn't device specific.

    The stepper code takes a "plan" block, which is a linear segment with an entry speed and an exit speed, and sets up a bunch of info for the stepper interrupt handler, and that interrupt is the thing that drives the output pins. While I don't think it'll be simple to re-code, it'd be much easier to just re-work the stepper module to use a cog with variable delays than it would be to emulate an AVR interrupt and pin set on the Prop. The planner module is pretty heavily commented, as is the part of the stepper module that deals with the plan blocks. The interrupt isn't documented quite as well, but reading through it, there's enough info given in the other two areas to re-implement it.
  • jmgjmg Posts: 15,148
    JasonDorie wrote: »
    ....

    The stepper code takes a "plan" block, which is a linear segment with an entry speed and an exit speed, and sets up a bunch of info for the stepper interrupt handler, and that interrupt is the thing that drives the output pins. While I don't think it'll be simple to re-code, it'd be much easier to just re-work the stepper module to use a cog with variable delays than it would be to emulate an AVR interrupt and pin set on the Prop. The planner module is pretty heavily commented, as is the part of the stepper module that deals with the plan blocks. The interrupt isn't documented quite as well, but reading through it, there's enough info given in the other two areas to re-implement it.

    Yup, that was where I suggested splitting the resource in the other thread. (with added time-stamps, to keep multi axes in sync)
    Prop can manage linear vectors quite easily, and one COG per axis makes it even simpler to expand.
    I think it should be possible to feed that information over a serial link, to any distribution of slaves, from some master.
    The master could be RaspPi, or AVR running the higher level 'hairy' code.

  • There should be no need to have a cog per axis. The synchronization would be harder than just running it all in one core, I'd expect. Since everything is linear segments with pre-computed timing coefficients, it just means running a simple bresenham-like algorithm to keep the motors in sync, and varying the timing between steps.
  • jmgjmg Posts: 15,148
    JasonDorie wrote: »
    There should be no need to have a cog per axis. The synchronization would be harder than just running it all in one core, I'd expect. Since everything is linear segments with pre-computed timing coefficients, it just means running a simple bresenham-like algorithm to keep the motors in sync, and varying the timing between steps.

    That's true, up to a point. Higher axis counts have been mentioned (up to 6?) and faster step speeds are another trend, so I was looking more future proof.
    Would be interesting to see numbers on the step-rates a single-cog can manage, for say, 6 axis ?

  • If it was implemented in PASM or LMM, and single cog should be able to handle a lot. Bresenham lines are, per axis:

    - Add a term to an axis counter
    - If that term goes > 0, subtract a reset count from it

    To do multi-axis synchronization, you use the "time" axis to drive the others, and oversample all axis by 2x or 4x to avoid jitter. To handle acceleration / deceleration, you add code to the loop to adjust the loop timing per step.

    It doesn't *have* to be bresenham, that's just a convenient way of representing it. You're essentially planning, per axis, what time the next output pulse has to be sent, then waiting for the minimum of all axis times to elapse. You check each axis to see if it needs to be pulsed, and for any that did, you compute the next pulse time and repeat. You can pre-compute most of the math per line segment per axis so it ends up being a couple shifts, add, sub, and a div, per axis, per step.

    From my robot arm controller:
    int CalcStepDelay( int n, int PrevDelay )
    {
      return PrevDelay - (PrevDelay << 1) / ((n<<2) + 1);
    }
    
    void Motor::Tick(void)
    {
        if( CurStep < TotalSteps )
        {
            if( (TickTime - (int)_CNT) < 0 )
            {
                _OUTA |= StepMask;
                CurStep++;
    
                if( CurStep < AccelSteps ) {
                    Cn = CalcStepDelay(CurStep , Cn);
                }
                else if( CurStep > DecelStart ) {
                    int n = CurStep - TotalSteps;
                    Cn = CalcStepDelay(n , Cn);
                }
    
                TickTime += Cn >> 8;
                _OUTA &= ~StepMask;
            }
        }
    }
    

    AccelSteps is how many steps you're accelerating for in this move to reach top speed for the axis, and DecelStart is the step index where this axis will begin decelerating. This would be computed per segment by a different cog. Cn is a Count at time(n) variable, stored as 24.8 fixed point for accuracy.
  • idbruceidbruce Posts: 6,197
    edited 2017-03-26 23:39
    Okay, since we are talking about it....

    Of course it would be nice to have canned code to use at a whim, but there is also the subject of multi-axis machines, as indicated by jmg.

    In addition to the crazy scheme I presented in this thread, I am also intrigued by the idea of using the Propeller as a multi-axis syncronizer, such as this chip: novaelec.co.jp/eng/MCX514_e.html

    With this chip, they claim multi-chip interpolation and show 8 axes being controlled, and I would imagine that more are obtainable, by simply adding more chips.

    It is my intention, to brush up on my algebra, as well as brief studies of other subjects, so that I can move on to motion physics. I want to be able to understand all this motion planning code, or better yet, plan my own.

    Anyhow, once again, I may be crazy, but I believe the Propeller can do a quite a few things that these chips can do, if limited to steppers without encoders.

    EDIT: However, when the P2 arrives, that should open up a wider range of possibilities.
  • jmgjmg Posts: 15,148
    JasonDorie wrote: »
    From my robot arm controller:
    Looks good, what size does that compile to, COG targeted, and what loop-time does that code have ?

  • Hi

    Are all the movements linear or straight?
    Are curves made up of multiple short straight moves?
    Am I correct in assuming the 'algorithm' for the synchroinising of multiple axes is 'tied' to the axis with the greatest number of steps ie-
    For the axis with the greatest number of steps, that axis will step each tick (or clock), and the other axis have to decide- do I step or not-, and that is determined by the bressingham.
    For acceleration the clock or tick rate for the algorithm is controlled and all the others just fall into step automagically.
    I've been going to have a stab at this for a while and it seems to me that no matter how many axis there are, they can all be controlled in this way for a STRAIGHT move.
    Incidentally it seems to me that for each move a different axis might become the 'master' or synchronising axis depending on which axis has the greatest number of steps.

    Dave
  • From what I know, that sounds just about right. However, linear movements are just one part, then there arcs and helicoil movements
  • Grbl breaks all moves into relatively small linear segments and does path planning on the result. It's certainly possible to do arcs on a micro, but it's tricky to be step-precise if your starting point isn't on a nice 90 degree bound.
  • @jmg - I haven't tried compiling this to COG before, but implemented in pasm I'd expect it to be in the neighborhood of 400 clocks per axis, max, if you're doing the divide.
  • Jason
    but it's tricky to be step-precise if your starting point isn't on a nice 90 degree bound.

    What do you mean by "a nice 90 degree bound"?
  • Orthogonal. Start of arc on X or Y axis.
  • Yes - if you start / end an arc on a 90 degree boundary, you can get a perfect, step accurate arc quite easily. If you start at an arbitrary angle you're at the mercy of the accuracy of your sin/cos functions, and possibly atan, depending on how the arc is defined.

    With GCode, arcs are often defined by the current starting point, a center point, and an end point. If you expect to end on the integer step defined by that end point, you need very accurate functions to get you there. In my PropLaser code I allow a "slop" of about 10 steps for the destination point, and that seems to work - it does step accurate arcs much faster than piecewise linear, but I don't handle accel/decel while running them.
  • jknightandkarrjknightandkarr Posts: 234
    edited 2017-04-02 19:36
    I have a 3d printer that's Arduino driven. I actually have the code and planned to figure it out, and make a propeller version of it. My problem is I don't know Arduino that well and the code has code in it thats not just arduino, so I gotta really do work figuring it out. I want to make my own 3d printer from scratch and being able to add features would be nice. My internet is out so I get on when I can, will check back on this when I can.

    Joe
Sign In or Register to comment.