[Grbl_Esp32 Issue#244] Spindle PWM invert option

未分类 bolang 4个月前 (10-14) 33次浏览

Issue #244 | 状态: 已关闭 | 作者: owenduffy | 创建时间: 2019-10-08

标签: enhancement


I would find an option to invert spindle PWM output of advantage.

Some ‘break out boards’ have on board PWM to analogue converters that require inverted PWM.

The feature will appeal to users of popular Chinese CNC routers that have such boards fitted (the parallel port BOBs) in avoiding a makeshift hardware inverter.

It seems that Mach3 provides such an option, certainly boards such as the TX14692 and its many variants use inverted PWM.


评论 (29)

#1 – bdring 于 2019-10-08

I’ll take a look at that later this week to see if it can be easily and cleanly added.


#2 – bdring 于 2019-10-11

I think I have this working. I am doing an overall cleanup of the spindle at the same time, so I need to do some more testing.

Previously, if you did not specify a spindle pin, you still needed to define a bunch of spindle values to get it to compile. Now, if you don’t specify the pin, the other values are not needed.


#3 – owenduffy 于 2019-10-11

Ok, sounds good Bart. Happy to test when you are ready.

Please see issue #247 which relates to spindle control and user customisation… it is a very simple enhancement probably to the same module if it fits with your ideas on user customisation.


#4 – bdring 于 2019-10-11

I saw that issue. I wanted a clean PR on the invert issue before I look at that other issue. There is also the #define ENABLEPIECEWISELINEARSPINDLE feature of AVR Grbl that was never implemented in GrblESP32.

How are you measuring spindle speed?

How well does it hold RPM under load?


#5 – owenduffy 于 2019-10-11

Measuring speed:

All tests are unloaded on a CNC6040 1.5kw 2pole induction motor VFD. The VFD controller displays VFD supply frequency. Induction motors have slip which is load dependent (it is the mechanism by which motor current increases to meet the load requirement), and I have verified the spindle speed unloaded reconciles with freq display using an optical tacho on the shaft (ie unloaded slip is very low as expected).

I would argue that unloaded speed is the target, as cutter burning on light cuts is related to near unloaded speed. In this context, I think you suffer loss of speed under load as an essential characteristic of the motor.

This particular VFD is not very stable unloaded at low rpm, and I expect even less so when loaded. There are practical limits to speed control.

I expect that slip at high speed is probably small, but at the lowest frequency / speed where winding reactance is lower relative to winding resistance, the slip curve is probably less ideal. Did I say there are practical limits to speed control?

The exit idea I proposed does not limit the compensation to a piece wise one, though I saw the warning to keep the code path length short.


#6 – bdring 于 2019-10-11

The changes have been uploaded to the devt branch. I will leave them there for a while before merging with master.

Any testing you can do or feedback you have is appreciated.


#7 – owenduffy 于 2019-10-11

I should be able to do that today (UTC+11).


#8 – owenduffy 于 2019-10-11

I have tested it initially with a scope on the output.

Verified that it is inverted, but there is an issue at speeds below $31 speed in that I expected PWM of 0% (inverted) but it is providing 1.56µs (I assume PWM=1/256) and we really want PWM=0 when speed is below S31 don’t we?

If I set speed S2000, I get 10.15µs (inverted fine), and them M2 and PWM=770ns, we need 0ns to turn the motor off.

Have I been clear?


#9 – bdring 于 2019-10-11

I didn’t test that. I never liked the way that works. It seems like it is not very robust.

Is the purpose of that to make sure you run the spindle at a minimum RPM or a minimum PWM?

I think it should just change any non zero Sxxx below your minimum to the minimum and send it through the same calcs as any other S value. Otherwise, unless SPINDLEPWMMIN_VALUE is perfect you have am odd transition from below minimum to the minimum.

Also

I think S should be tested and fixed in gcode.cpp. If you you send S100 it would change it to S200 (if that is the min). Now the $G reporting and overrides, etc work on the right value.


#10 – owenduffy 于 2019-10-11

Ok, I think the system needs to send PWM 0% (non-inverted or inverted as per config) whenever the motor is stopped, program is stopped, or Sxxxx


#11 – owenduffy 于 2019-10-11

I might explain that the reason I think the spindle should be stopped for sxxxx


#12 – bdring 于 2019-10-11

I am not sure how it saves the edge finder if you set the RPM too high.

I suppose if you are really worried about all this stuff, you will set it up correctly. Maybe I’ll mostly leave it alone.

How about this…

Example:
settings.rpm_min = 200
settings.rpm_max = 1000

S0 = 0 PWM
S100 = SPINDLEPWMMIN_VALUE
S200 = 200 RPM
S1000 = 1000 RPM
S1200 = 1000 RPM (and reports 1000)


#13 – owenduffy 于 2019-10-11

Let me try to say it more clearly.

The system should send PWM=0% (inverted or not as configured) for:
-Sxxx


#14 – owenduffy 于 2019-10-11

>
>
> I am not sure how it saves the edge finder if you set the RPM too high.
>
> I suppose if you are really worried about all this stuff, you will set it up correctly. Maybe I’ll mostly leave it alone.
>
> How about this…
>
> Example:
> settings.rpm_min = 200
> settings.rpm_max = 1000
>
> S0 = 0 PWM
> S100 = SPINDLEPWMMIN_VALUE
> S200 = 200 RPM
> S1000 = 1000 RPM
> S1200 = 1000 RPM (and reports 1000)

S100 = 0 PWM

Reasoning:
do not spin a tool faster than requested, it may be unsafe for the tool, work, operator.
do not spin the motor slower than rpm_min (unless you stop it).


#15 – bdring 于 2019-10-11

I disagree.

Reasoning:

Never accept an RPM but not spin.

Here is “original” Grbl.


else if (rpm <= settings.rpm_min) { if (rpm == 0.0) { // S0 disables spindle sys.spindle_speed = 0.0; pwmvalue = SPINDLEPWMOFFVALUE;
} else { // Set minimum PWM output
sys.spindlespeed = settings.rpmmin;
pwmvalue = SPINDLEPWMMINVALUE;
}

The alternative is error, stop job, require reset.


#16 – owenduffy 于 2019-10-12

Ok, I understand and accept.

I am about to do a cal run to feed the py script for piecewise linearisation. I am running it on the devt version, and a dry run looks good. The optical tacho will log the actual spindle speed (unloaded).


#17 – bdring 于 2019-10-12

Great.

Do you think a SPINDLERPMRANGE_ERROR should be added?


#18 – owenduffy 于 2019-10-12

I don’t understand.

The cal run looked good with the devt branch. Iie I am using the inversion.)
!line_fit


#19 – owenduffy 于 2019-10-12

I have been going over this, and I think there remains an issue that when the spindle should be stopped, there is a very short (790ns) down pulse in each PWM period.

I have found that if I set sxxx>0 and analogWrite(SPINDLEPWMCHANNEL, (1<PWMBITPRECISION) – 1);
grblanalogWrite(SPINDLEPWMCHANNEL, (1<PWMBITPRECISION));

The problem goes away with this revised line.


#20 – bdring 于 2019-10-12

I saw that issue too.


#21 – owenduffy 于 2019-10-12

You have partially implemented the piecewise compensation.

I added the code into spindle_control.cpp:

text
@@ -61,11 +61,12 @@ void spindle_stop()
spindlesetenable(false);
#ifdef SPINDLEPWMPIN
#ifndef INVERTSPINDLEPWM
grblanalogWrite(SPINDLEPWMCHANNEL, SPINDLEPWMOFFVALUE);
#else
- grblanalogWrite(SPINDLEPWMCHANNEL, (1<PWMBITPRECISION) - 1);
+// grblanalogWrite(SPINDLEPWMCHANNEL, (1<PWMBITPRECISION) - 1);
+ grblanalogWrite(SPINDLEPWMCHANNEL, (1<PWMBITPRECISION));
#endif
#endif
}

uint8t spindlegetstate() // returns SPINDLESTATEDISABLE, SPINDLESTATECW or SPINDLESTATE_CCW
@@ -138,15 +139,31 @@ uint32t spindlecomputepwmvalue(float rpm)
pwmvalue = SPINDLEPWMMINVALUE;
}
} else {
// Compute intermediate PWM value with linear spindle speed model.
// NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight.
- sys.spindle_speed = rpm;
- pwmvalue = floor((rpm-settings.rpmmin)*pwmgradient) + SPINDLEPWMMINVALUE;
- }
-
- return(pwm_value);
+ #if (N_PIECES > 3)
+ if (rpm > RPM_POINT34) {
+ pwmvalue = floor(RPMLINEA4*rpm - RPMLINE_B4);
+ } else
+ #endif
+ #if (N_PIECES > 2)
+ if (rpm > RPM_POINT23) {
+ pwmvalue = floor(RPMLINEA3*rpm - RPMLINE_B3);
+ } else
+ #endif
+ #if (N_PIECES > 1)
+ if (rpm > RPM_POINT12) {
+ pwmvalue = floor(RPMLINEA2*rpm - RPMLINE_B2);
+ } else
+ #endif
+ {
+ pwmvalue = floor(RPMLINEA1*rpm - RPMLINE_B1);
+ }
+ }
+ sys.spindle_speed = rpm;
+ return(pwm_value);
#else
return(0); // no SPINDLEPWMPIN
#endif
}

`

and cpu_map:

`text
@@ -126,12 +126,14 @@
// round down to nearest bit count for SPINDLEPWMMAX_VALUE = 13bits (8192)

#define SPINDLEPWMBASE_FREQ 5000 // Hz
#define SPINDLEPWMBIT_PRECISION 8
#define SPINDLEPWMOFF_VALUE 0
- #define SPINDLEPWMMAX_VALUE 255
- //#define INVERTSPINDLEPWM
+// #define SPINDLEPWMMAX_VALUE 255
+#define INVERTSPINDLEPWM
+#define SPINDLEPWMMIN_VALUE 3
+#define SPINDLEPWMMAX_VALUE 195

#ifndef SPINDLEPWMMIN_VALUE
#define SPINDLEPWMMIN_VALUE 1 // Must be greater than zero.
#endif
`

and config.h:

`text
@@ -45,11 +45,12 @@ Some features should not be changed. See notes below.
// Define CPU pin map and default settings.
// NOTE: OEMs can avoid the need to maintain/update the defaults.h and cpu_map.h files and use only
// one configuration file by placing their specific defaults and pin map at the bottom of this file.
// If doing so, simply comment out these two defines and see instructions below.
#define DEFAULTS_GENERIC
-#define CPUMAPTESTDRIVE // these are defined in cpumap.h
+//#define CPUMAPTESTDRIVE // these are defined in cpumap.h
+#define CPUMAPESP32 // these are defined in cpu_map.h
#define VERBOSE_HELP // adds addition help info, but could confuse some senders

// Serial baud rate
#define BAUD_RATE 115200
@@ -687,30 +688,27 @@ Some features should not be changed. See notes below.
#define DISABLELASERDURING_HOLD // Default enabled. Comment to disable.

// Enables a piecewise linear model of the spindle PWM/speed output. Requires a solution by the
// 'fitnonlinearspindle.py' script in the /doc/script folder of the repo. See file comments
// on how to gather spindle data and run the script to generate a solution.
-// #define ENABLEPIECEWISELINEAR_SPINDLE // Default disabled. Uncomment to enable.
+#define ENABLEPIECEWISELINEAR_SPINDLE // Default disabled. Uncomment to enable.

// NPIECES, RPMMAX, RPMMIN, RPMPOINTxx, and RPMLINEXX constants are all set and given by
// the 'fitnonlinearspindle.py' script solution. Used only when ENABLEPIECEWISELINEAR_SPINDLE
// is enabled. Make sure the constant values are exactly the same as the script solution.
// NOTE: When NPIECES < 4, unused RPMLINE and RPM_POINT defines are not required and omitted.
-#define N_PIECES 4 // Integer (1-4). Number of piecewise lines used in script solution.
-#define RPMMAX 11686.4 // Max RPM of model. $30 > RPMMAX will be limited to RPM_MAX.
-#define RPMMIN 202.5 // Min RPM of model. $31 < RPMMIN will be limited to RPM_MIN.
-#define RPMPOINT12 6145.4 // Used NPIECES >=2. Junction point between lines 1 and 2.
-#define RPMPOINT23 9627.8 // Used NPIECES >=3. Junction point between lines 2 and 3.
-#define RPMPOINT34 10813.9 // Used NPIECES = 4. Junction point between lines 3 and 4.
-#define RPMLINEA1 3.197101e-03 // Used N_PIECES >=1. A and B constants of line 1.
-#define RPMLINEB1 -3.526076e-1
-#define RPMLINEA2 1.722950e-2 // Used N_PIECES >=2. A and B constants of line 2.
-#define RPMLINEB2 8.588176e+01
-#define RPMLINEA3 5.901518e-02 // Used N_PIECES >=3. A and B constants of line 3.
-#define RPMLINEB3 4.881851e+02
-#define RPMLINEA4 1.203413e-01 // Used N_PIECES = 4. A and B constants of line 4.
-#define RPMLINEB4 1.151360e+03
+#define N_PIECES 3
+#define RPM_MAX 23935.2
+#define RPM_MIN 2412.2
+#define RPM_POINT12 6283.9
+#define RPM_POINT23 11866.0
+#define RPMLINEA1 4.390865e-03
+#define RPMLINEB1 7.591787e+00
+#define RPMLINEA2 1.074874e-02
+#define RPMLINEB2 4.754411e+01
+#define RPMLINEA3 9.528342e-03
+#define RPMLINEB3 3.306286e+01

/* ---------------------------------------------------------------------------------------
OEM Single File Configuration Option

This is with cal factors based on my cal run yesterday.

It works on a bench test observing with the scope.

I should be able to run on the machine this morning (weather permitting).

If that is good, it wraps up #244 and #247.


#22 – owenduffy 于 2019-10-12

I played with the model fit a bit (changing parameters in the py file), and got a better fit.

This test is with the devt branch with the changes shown earlier to fit the rest of the spindle compensation… and importantly, with inverted spindle PWM.

At the outset:
!Clip 054

After compensation:

!Clip 055

Clearer combined:
!Clip 056

Much better calibration.

Bart, it works a treat… if you incorporate the rest of the spindle compensation, you can close this and #247.

Thanks for your work… Owen.


#23 – bdring 于 2019-10-12

I don’t see where #define ENABLEPIECEWISELINEAR_SPINDLE is used in your code.

That code is a lot of work to read in that +/- format.


#24 – bdring 于 2019-10-12

OK…looking at original Grbl. It surrounds everything to make an alternative version of the function


#25 – owenduffy 于 2019-10-12

It was enabled elsewhere in config.h (just above the stuff I quoted). Shouldn’t work without it!!!

Essentially, I anticipated the piecewise code you would add into spindle_control, copied literally from grbl.

I expect you to copy from grbl rather than my code above. I showed that to show the extent of what has been tested.

Happy to retest when you merge the new stuff into devt.


#26 – owenduffy 于 2019-10-12

You are thinking I should have forked this and made the changes… but as it is, you are the author and you are more familiar with the code base, I am happy to do the testing.


#27 – bdring 于 2019-10-12

I pushed more changes to devt. It is not easy for me to test.

I made the linear fit a separate function to clean things up and it could allow easier ways to add other fit methods in the future.


#28 – owenduffy 于 2019-10-13

Happy to test.

Ok, looks good on a test with the scope (which reveals more than running the machine).

I think that is good to promote.

Thanks again… Owen.


#29 – bdring 于 2019-10-13

Merged


原始Issue: https://github.com/bdring/Grbl_Esp32/issues/244

喜欢 (0)