gnea / grbl-Mega

An open source, embedded, high performance g-code-parser and CNC milling controller written in optimized C that will run on an Arduino Mega2560
https://github.com/gnea/grbl/wiki
Other
486 stars 223 forks source link

Spindle Synch Solutions #58

Open shooter64738 opened 6 years ago

shooter64738 commented 6 years ago

Afternoon all! This is partly to describe how I have gotten spindle synch to work for myself, and partly to see if its 'correct' and maybe get some input on the matter.

Mode 1: When G95 is active, I can move 2 axis' with regular gcode. For example in G17 I can move X and Y with G commands, but I cannot readily move Z. In G18 I can move Y and Z but not readily X, and G19 I can move X and Z but not readily Y. To move that other axis, I have to rotate my spindle, either by hand or under power. If the spindle is rotating, the axis (which I refer to as the vertical axis) will move at a rate relative to the spindle. For milling this gives me an ability to rigid tap. (I have not wrapped it up in a neat little canned cycle yet) Example: g0x10y10 (to a location with a hole I intend to tap) g1z-10f.7 (feed .7mm for each rotation of the spindle, max travel is -10) When Z reaches its depth of 10mm, it shuts the spindle off then reverses the spindle. Since Z does not move unless the spindle is rotating, when the spindle is rotated in reverse, the Z moves in the opposite direction. Since it was going to a negative space with CW rotation, it will now go to a positive space with CCW spindle rotation. How: There seemed to be 2 control pins (system.h/c) that were not in use presently on the mega version of grbl. The port was already set up for pin change interrupts so I just used that port. I have a nano board that controls my spindle, and I added an encoder to the spindle and I feed its data to the nano. The nano reads the encoder data and once it has accumulated enough encoder pulses to cause the axis minimal movement it sends a stepper pulse to those 2 control pins. One pin sets the direction of the stepper pulse, and the other feeds directly to the stepper control in grbl. Moving per rotation causes some significant problems, so instead of moving a distance per 'rotation', I move a distance per encoder pulse. A fractional rotation of the spindle moves a fractional distance on the 'vertical' axis.

Mode 2: This one... yikes, got complicated. grbl is mainly driven by the timer. When G95 is active I dont allow the timer to enable. What controls motion then is that same pulse/direction data on the control port. Example: g0x10Y10 (to a location I want to tap) Nothing happens... until you rotate the spindle. Then X and Y both move to the location. Once they arrive at the location, they stop moving. I did have the stepper pulses increment and decrement depending on spindle direction. So if it started at 0, and got to 5 with CW spindle motion, and suddenly decided to go CCW, they would move back to where they started until the step count got to zero and then CCW spindle rotation had no effect. (I changed this later due to some direction complications) Then for tapping: g1z-10f.7 (feed .7mm for each rotation of the spindle, max travel is -10) The spindle stops when the depth is reached. I had some trouble with reversing the spindle here because I was going - with CW, and now I want to go + with CCW, but I have to first issue a new Z motion that goes positive and ignore the direction information from the spindle. Ultimately it seems to work more effectively if I just ignored spindle direction all together and just let the motion execute in time with the spindle rotation. Again this got super complicated and messy and im not 100% sure its even right.

So I tried rigid tapping on a commercial fadal vmc and (its a vertical mill only) it ONLY moves the z axis with spindle rotation. so for milling maybe mode 1 was correct. (Could be that the machine is also old and just doesnt have the ability). For a lathe, I dont know for sure. But even if you used mode 1 on a lathe you could still do threading pretty easy. You wouldn't be able to run a cross feed at the same time but I wouldn't think you would need too for lathe threading either. Im not much of a machinist though, so perhaps brighter minds know better.

Also I dont know of any problems that might arise in grbl by controlling the steppers directly. I do run the synch update methods so that its reported position is always correct, and so far it seems ok. Again brighter minds (in particular @chamnit)

Thats what I have done so far, and all changes to grbl have been wrapped in #ifdef tags so finding, moving, removing, adding the changes I made should be pretty easy if its usable in the future. If someone can describe for sure which way is the more correct way, I'll put some more time into it. I vote for mode 1. Its much easier!

109JB commented 6 years ago

It is impressive that you have this working. However, G95 should work on all axes, not just one. For example

G95 ; Program with G95 (F= mm/rev.) G1 Z-20 F0.2

Will move the Z axis 20 mm in 100 revolutions (20/0.02). However,

G95 G1 X20 Y20 Z20 F0.2

is a bit more complicated. first the distance to move is sqrt(20^2 20^2 20^2) = 34.64 mm, so the move will complete in 34.64 / 0.2 = 173.2 revolutions, and all three axes move in coordinated motion making a straight line from start to end.

Since G95 is a common standard G-code on industrial interpreters, and your implementation doesn't match the common standard, I would recommend just using a different G-code for the type of motion you have implemented. Something in the range of G100 to G200 should be unused by Industrial or 3d Printer standards.

--For rigid tapping the axes that are moving should basically be geared to the rotation of the spindle. Threading on a manual lathe is done just this way using mechanical gears. What needs to be done in CNC is mimic how a mechanically linked setup would work. For rigid tapping on a milling machine this gearing is necessary because the spindle has to slow to a stop, reverse, then accelerate back to speed to exit the hole. All during this time the tap depth has to remain in the correct in relation to spindle rotation or the tap will break. The below linked video is not tapping, but rather gear hobbing , but it shows how the axis being linked to the spindle should follow the spindle no matter what. About the 50 second point in the video the guy rotates the spindle back and forth by hand and the rotary axis responds in kind. That is what you want for successful rigid tapping. The only difference being that tapping would use a linear axis rather than the rotary axis.

https://www.youtube.com/watch?v=ZhICrb0Tbn4

--On a lathe there are times when you may want to syncronize motion of X and Z axes both to the spindle. Imagine making a tapered thread as a simple example of this.

-- Also, have you taken into account that for lathe threading with multiple passes each successive pass has to follow the previous one exactly. So, Z-axis position has to use an index pulse or something else to know exactly the spindle position for starting the move.

shooter64738 commented 6 years ago

Thanks Jb. I have seen that video and I tried to closely mimic what that video shows, although I dont know if he is locking one axis to the spindle or all of them.

I know on old school lathes for threading you have to come in 'on a number' it didnt matter which number but it had to start feeding on one of the numbers or it might not cut the same thread path twice. That I think could be handled by knowing the spindle angle at the time motion started. It would complicate it some but I dont think too bad.

What really made this complicated was, what to do if the spindle is running cw and you have a motion running, perhaps a looong motion, and then you decide to reverse the spindle. Should it keep traveling in the same directions it was going before the spindle changed to ccw, or should it reverse? Reversing mode 1 was simple, because there was not really any axis coordination. Mode 2 on the other hand.. I had it reversing but it became quit a messy operation code wise.

I was letting the grbl planner handle all the processing, planning, euclidean math, and just driving it with the encoder instead of the timer. I'll put some more thoughtinto it.. Get a bigger marker board and a huge pot of coffee..

Also, dont ever forget when you have g95 on, then suddenly running your spindle up to 5000rpm will make holes in your mill vice. Rather quickly.

langwadt commented 6 years ago

@shooter64738 "come in 'on a number' it didnt matter which number" is oversimplifying it, it'll depends on whether the pitch is even/odd/fractional and if you are doing metric on an imperial lathe or vice versa you usually have to keep the half nut engaged

shooter64738 commented 6 years ago

Would it still be an oversimplification to start the feed as jb describes with a z index pulse, or at a set angle? Such as start feed at angle zero?

109JB commented 6 years ago

I guess I should explain my point of view. I am most interested in spindle sync for lathe use, and not so much for milling machine use.

On milling machines the sync would be for tapping, but I generally just tap on the bench using a cordless drill. So for milling machines, it is not a big concern for me. G95 on a mill means much more complicate math because a true implementation would take into account all axes, circular interpolation, etc. Sync on a mill is not absolutely necessary and overly complicated

On lathes on the other hand, lack of spindle sync means no threading, and on a lathe this is basically a deal killer in my opinion. So to keep thing simpler, I would stick firstly to what is required to do linear lathe threading. So lets dive into that.

As said before, since the lathe threading most commonly used is single point multiple pass, you have to be able to sync the feed to the spindle rotation, and then be able to repeat it on successive paths. If you use an encoder that has an index pulse, then using the index pulse to trigger the start of the movement should work fine as long as the Z position is "the same" on each pass. I think this should be able to be taken care of in the GUI rather than within Grbl. When lathe threading each successive pass the tool is fed in at an angle rather than straight along the X axis to keep the cutting edge on the left side of the tool. But if the tool start position is simply moved by the GUI at that angle for the second pass, then starting the sync feed on the index pulse should work fine.

If you can sync just the Z axis (Carriage) that will take care of 99% of the threading needs on a lathe. Being able to sync both X and Z would cover tapered threads. With tapered threads the feed is still Z dependent, meaning that the thread pitch is measured parallel to the Z axis. So, say for a 0.1mm thread pitch Z would move 0.1mm for each rev regardless of the thread being a straight thread or tapered. For a tapered thread the X would move based on the taper and be tied to the Z axis movement.

We can get more complicated with lead out at the end of a thread, but it isn't necessary in my opinion. I mostly prepare an undercut at the end of the thread where the tool stops its pass like the picture below. This way the tool can just stop there with the spindle still running and it won't be cutting anything.

The above would be the simplest to get it working on a lathe.

One other thing. It sounds like you made this synced motion a modal or persistant mode. Since it doesn't fit perfectly with the G95, I think I would personally make it a non-modal or one time use command where the user has to invoke the G95 or whatever each time they want to use it.

I'm excited about what you are doing. I have been waiting for someone to tackle this for lathe threading for a long time. I would have done it myself but don't have the coding skills to do so. Thank You for what you are doing. I'm hoping you plan to make your modifications available to the community. Let me know if you need more help.

shooter64738 commented 6 years ago

Good info! Yes I have a repository setup on git hub, its just a slow process for one guy but im getting there. Itll be up there as i get it working. Did have a couple people helping but they dwindled down.

Im a programmer that dabbles in machinery so I i know I've got some limitations to over come with knowledge, and im still gettimg back in my c groove.

I'll work on fine tuning coordinated motion driven from the encoder. That seems to be more inline with the standard operation.

109JB commented 6 years ago

@shooter64738

Any more progress?

shooter64738 commented 6 years ago

Ive made some progress.. Havent had too much time to dedicate to it, but the weekend is coming up.

I did get to spend some time with a Nakamura lathe, and the operator doesn't believe that changing spindle direction in the middle of a gcode line will change direction of travel. The motion will continue in the same direction it was started in until it reaches the end of its motion. I couldn't try it because the cutter would be running backwards on the part, not to mention I cant rotate it by hand.

So at the present time I am still working on getting the spindle motion to drive the execution of the gcode, but once the motion starts it doesn't reverse with the spindle. In other words if you program g1x1z-5, any spindle motion (cw or ccw) will cause X to move towards 1, and Z to keep moving towards -.5. As X and Z approach their targets, the spindle should slow down until it stops at the point X and Z reach their destinations. At this point the next line of gcode would be loaded and the spindle would again drive it to the target. There is some differences in cycles and actions between lathe and mill machines, so I'm working with that in mind.

I think a rigid tapping cycle on a mill could be self contained. When a rigid tapping cycle is executed, the mill can drive the Z down to a destination, Then when spindle reverses the Z can come back to either its g98 or g99 location. Similar to a drill cycle. In that operation the spindle direction would decide if motion is going forward or backward. However its only doing it on that 1 line of gcode. Hoping to make some good progress in the next week or so.

109JB commented 6 years ago

Yeh. For lathe threading there shouldn't be a need to worry about reversing. Most lathe operations that need sync would be threading and would not need to reverse. I think what you may have been thinking about here is the video where the spindle was "geared" to the extra axis, but this was for a gear hobbing setup and is something different. For the lathe, I think reversing shouldn't be a problem.

For the mill and rigid tapping it would be a need to keep the axis linked to the spindle even during spindle reversing.

langwadt commented 6 years ago

this is quite interesting, https://youtu.be/BAAio27mxKI?t=20m35s

shooter64738 commented 6 years ago

So I didn't get much done code wise, but I did do more research on this subject, and spent some time talking to an older guy at a shop that knew something about building commercial machines. And now, I think it all makes sense, so correct me if I am wrong.

G95 is not exactly spindle 'synch' Its a feed mode to execute coordinated motion based on spindle speed. In most cases it is the programmed speed, because most machines have a spindle controller and once given a spindle speed, it will govern the spindle to keep it at that speed. Most commercial mills/lathes have pretty large spindle motors though so maintaining this speed is not usually too much of a problem. The spindle speed is governed by only a single pulse indicating a rotation. Where the spindle is at exactly in that rotation is irrelevant, so long as the axis moves at a predicted rate that will cause it to cover the specified distance by the time the spindle pulses again. So for milling, or turning its only going to affect the chip load produced if the actual spindle speed varies slightly from the programmed speed. If the spindle speed varies greatly under load, then that would be a problem. On the other hand higher end/larger machines may also have live spindle feedback (which is apparently called a spindle axis) and can reduce the execution speed to the actual spindle speed instead of programmed spindle speed. Mach3 for example can use programmed speed to calculate the rate at which to move the axis's even if there's not a working spindle encoder. It can also be setup to use live feedback, and in that circumstance, if you forget to turn on the spindle before you execute a motion, nothing may happen. Reversing the spindle is not relevant to G95. If there is spindle motion, the axis's move to their destinations. G95 would not stop/start/reverse the spindle, its just the mechanism to determine the speed at which the motion will execute. This could be accomplished by just having a spindle motor/driver combo that will hold the spindle at the commanded speed. I have a spindle controller running on a nano, and it tries really hard, but my new bldc is just not quit beefy enough to hold it at an exact speed under heavy loads. Or we could just not care too much about precise G95 coordination at the moment. Chip load would change under G94 as well since the motion is attempting to execute based on a time interval regardless of spindle speed.

Rigid tapping/thread turning.... This is my ultimate goal, and now that I think i have it understood, it's less complex than I first thought. The canned cycles perform these operations (the older fella did show me a G76 canned cycle for tapered threads on a lathe) and they are the ones responsible for reversing the spindle. In any of the canned cycles that require perfect synch with the spindle, and encoder IS required, not just an index pulse. Previously I thought for either operation an encoder would be required. The canned cycle is driven to its destination by the spindle, but the spindle must be slowed to a stop as it reaches its destination. Then reversed, until it reaches its clearance point (g98/g99). Then the cycle is done. These operations ARE tied to the spindle, and its as if the spindle controller its self is driving the axis instead of the axis controller. The same behavior is expected on lathe threading or mill threading/tapping. Any cycle that requires perfect synch will start at a specific place, it could be at the index pulse, but he (the older fella) said more than likely it will start at a specific spindle angle, because there are 1 start, 2 start, 3 start, 4 start threading operations on a lathe, and it will start motion at a specific angle for each start. I don't know exactly how to calculate the starting point but I'll figure it out.

So I guess in my long winded description/epiphany in a summary would be this:

  1. G95 is a feed rate mode based on spindle RPM (either real or programmed). That is all. It should not change motion directions, or affect motions in any way other than cause a calculated amount of motion per revolution, regardless of spindle direction. If the spindle only has an index pulse it can only be as 'in synch' as a single revolutions rpm drift allows. If the spindle employs live feedback with an encoder or resolver it can more accurately synch the spindle to all axis motions.
  2. Spindle synchronization is (usually) only truly synchronized in a cycle which requires true spindle synch. (rigid tap on a mill, thread cutting on a lathe are 2 examples.) This does require an encoder or resolver on the spindle 'axis'
  3. I need to (i suspect) refactor quite a bit of what I have written so far, and get canned cycles working completely while keeping the overall picture in mind.
  4. Lastly @109JB, @langwadt the youtube video you had linked previously is (as noted) a bit of an odd ball, as I couldnt find and (the older guy) didn't know a 'typical' way to set this up in gcode, However if I can keep the 'gearing' of an axis(s) programmable, doing something as demonstrated in the video should be pretty easy to accomplish for the end user. Hopefully that will make it fit just about every scenario anyone would want to use it in. (@langwadt I think this will allow some of what you linked to in your video as well)

Most of this may be what everyone was trying to explain to me already and I just wasn't getting the entire thing in my head. I think I have it now, unless someone can see an error in what I have described.

So back to the code for refactoring round 5 or maybe 6 now..

terjeio commented 6 years ago

@shooter64738 For 4. It must be the spindle that is synced with axis motion, not axis motion synced to the spindle - which we are trying to implement.

I think I have code ready that gives me in the region of 5uS resolution in calculating spindle position (about 0.2 degrees at 500 RPM if I am doing my calculations rigth), this with no real dependency on encoder resolution. The tricky part (for me) is how (and where) to use this to modulate the feed rate (in mm/min) to keep the controlled point on track...

terjeio commented 6 years ago

I think I am getting close to make lathe threading work on ARM (MSP432). I am using a 120 ppr encoder with index on my spindle providing feedback to a PID loop that I run on the start of each segment in a G33 block (except the first segment), the result from that is used to adjust the step timing. I have added logging to aid tuning and my last run resulted in recorded errors over 20mm of threads of less than 0.01mm - except during acceleration/deceleration that is. I still have to verify that this matches the physical result but it looks promising.

pid

Above is an initial PID-tuning display that I made: the red curve is the error (spindle angular position vs Z-axis position in the thread) - the initial spike during acceleration is 0.19mm settling down to within ±0.005mm thereafter. I do not know if this is acceptable as tolerance...

The blue and green lines are the programmed position vs spindle angular position - there are some green pixels visible but the line itself is mainly behind the blue.

I have a free running 32-bit timer @ 4MHz that I use to calculate the angular position of the spindle. The noise in the error signal is possibly due to imperfections in the spindle encoder (homemade) and latencies in the processor. Perhaps FFT-analysis can shed some light on that.

shooter64738 commented 6 years ago

I ran into a hardware issue with mine. In testing I can synch the axis motions just fine, but when its all setup and installed on the spindle, the encoder signal becomes errant due to vibration on the machine. It gets worse with more load on the spindle during a cut. I dropped down to a lower res encoder and it helped but the machine still 'jumps' by speeding up and slowing down. I'm in the process of building a heavier spindle for it to see if that helps. This maybe be why the commercial machines I looked at are using a resolver instead of an encoder. If nothing else just an index pulse with a predicted spindle position based on rpm may be better. What you have so far looks pretty good. Might think of some ways to isolate the encoder mounting when you install it on a machine. I mounted mine on rubber pads, and drive it with a small o-ring as a belt, but it still vibrates to much to keep the signal clean.

109JB commented 6 years ago

Here (http://7xcnc.com/hardware/encoder/) is an example of what can be implemented on a spindle for threading. It is not an encoder per se, because it won't be able to discern direction, but it works for threading. One optical switch for index pulse, and another for counting between index pulses. You could add a third and essentially make a big quadrature encoder that could sense direction.

As you mention though, many controllers use just a single index pulse, so you have options. For lathe threading, you can use a single index, index with some counting between, or full quadrature.

For rigid tapping you will need full quadrature so the controller can sense position and direction.

langwadt commented 6 years ago

if you only need speed and index, maybe do it like a crankshaft sensor. it's a magnetic sensor counting teeth on a "gear" commonly 60 teeth with two teeth missing as index

Harvie commented 5 years ago

Do you plan to support G95 (constant mm per revolution) mode? It should be very easy to do. Just multiply the feedrate by RPM which was set using S1000.