There may be a small issue with this code... Please post the Marlin_main.cpp file. If there is a problem, I'll edit it for you. But "Yes..." This is the code base you should be using now.
Printable View
There may be a small issue with this code... Please post the Marlin_main.cpp file. If there is a problem, I'll edit it for you. But "Yes..." This is the code base you should be using now.
Was there any version of this adapted for a delta?
Hello Roxy,
Ive been lurker here and just wanted to say thanks for the huge amount of help you've offered here.
I am just trying to use my z probe for the first time, so I thought I would start out easy by trying the M48, but it doesn't work.
First, I have a delta with a probe that is placed by hand (which means it doesn't need to be engaged or retracted, so just for now, I've inserted a return at the top of those routines) and the switch trigggers when at 18.21mm above the zero location (as determined by the paper test - it prints fairly well at this point.)
When I execute a M48 v3 the probe is lowered to Z_RAISE_BEFORE_HOMING, but then it just stays there, printing out a report with all the same values. Debug statements Ive inserted show the run_z_probe() getting repeatedly called, but nothing moves.
The m119 appears to work fine - the probe (hooked into zmin) is OPEN normally, and TRIGGERED when the switch is closed.
Any ideas?
The
static float probe_pt(float x, float y, float z_before, ProbeAction retract_action=ProbeEngageRetract, int verbose_level=1) {
function raises and lowers the probe. And it controls the engaging of the probe. Did you make modifications to it? Or are you just not calling it? Either way, why don't you post the code you changed so we can talk about it.
This code should work just fine with a Delta printer. However, with that said, my suspicion is that Delta printers are more susceptible to repeatability problems caused by different types of movements. If we knew what types of movements exposed those repeatability issues in Delta printers it might make sense to add a Delta option to the M48 command so the printer could be stressed harder.
With that said... It should work just fine and you should get a number to help you understand how good or bad your mechanics are.
Thanks for the help.
I am pretty sure that I am not using the code you are referring to that uses probe_pt(), so I went to try and get it by clicking on the "M48.c" link that is on the first post in this thread, but all I get is a black screen with
http://3dprintboard.com/attachment.p...5&d=1398698586
Then, I saw in the previous few posts that you specify a link to the main Marlin code, which I pulled and it looks identical to the code I have - the M48 code never calls probe_pt() but run_z_probe().
Looking at run_z_probe(), it does (in summary) calls to:
prepare_move_raw();
st_synchronize();
endstops_hit_on_purpose();
enable_endstops(false);
calculate_delta(current_position);
plan_set_position(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], current_position[E_AXIS]);
float zPosition = -10;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
st_synchronize();
// we have to let the planner know where we are right now as it is not where we said to go.
zPosition = st_get_position_mm(Z_AXIS);
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS]);
// move up the retract distance
zPosition += home_retract_mm(Z_AXIS);
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
st_synchronize();
// move back down slowly to find bed
feedrate = homing_feedrate[Z_AXIS]/4;
zPosition -= home_retract_mm(Z_AXIS) * 2;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
st_synchronize();
and then returns the Z position found.
So, it never makes a call to probe_pt(). However, this does not appear to be working in my config. It looks like it ought to work for a delta, but it always just returns without having moved the probe and returns the same Z position it started with. Kinda stuck.
Is odd that the probe_pt() routine is still in marlin_main.cpp, and it's called by the auto leveling command g29, but not g30, so I guess when M48 was "folded in" someone rewrote some of it? I kinda wanted to tackle g29 and g30 next, so I guess I need to figure out what's wrong with run_z_probe().
You are most welcome.
Try this:
Code:case 48: // M48 Z-Probe repeatability
{
#if Z_MIN_PIN == -1
#error "You must have a Z_MIN endstop in order to enable calculation of Z-Probe repeatability."
#endif
double sum=0.0;
double mean=0.0;
double sigma=0.0;
double sample_set[50];
int verbose_level=1, n=0, j, n_samples = 10, n_legs=0, engage_probe_for_each_reading=0 ;
double X_current, Y_current, Z_current;
double X_probe_location, Y_probe_location, Z_start_location, ext_position;
if (code_seen('V') || code_seen('v')) {
verbose_level = code_value();
if (verbose_level<0 || verbose_level>4 ) {
SERIAL_PROTOCOLPGM("?Verbose Level not plausable.\n");
goto Sigma_Exit;
}
}
if (verbose_level > 0)
SERIAL_PROTOCOLPGM("M48 Z-Probe Repeatability test. Version 1.85\n");
if (code_seen('n')) {
n_samples = code_value();
if (n_samples<4 || n_samples>50 ) {
SERIAL_PROTOCOLPGM("?Specified sample size not plausable.\n");
goto Sigma_Exit;
}
}
X_current = X_probe_location = st_get_position_mm(X_AXIS);
Y_current = Y_probe_location = st_get_position_mm(Y_AXIS);
Z_current = st_get_position_mm(Z_AXIS);
Z_start_location = st_get_position_mm(Z_AXIS) + Z_RAISE_BEFORE_PROBING;
ext_position = st_get_position_mm(E_AXIS);
if (code_seen('E') || code_seen('e') )
engage_probe_for_each_reading++;
if (code_seen('X') || code_seen('x') ) {
X_probe_location = code_value() - X_PROBE_OFFSET_FROM_EXTRUDER;
if (X_probe_location<X_MIN_POS || X_probe_location>X_MAX_POS ) {
SERIAL_PROTOCOLPGM("?Specified X position out of range.\n");
goto Sigma_Exit;
}
}
if (code_seen('Y') || code_seen('y') ) {
Y_probe_location = code_value() - Y_PROBE_OFFSET_FROM_EXTRUDER;
if (Y_probe_location<Y_MIN_POS || Y_probe_location>Y_MAX_POS ) {
SERIAL_PROTOCOLPGM("?Specified Y position out of range.\n");
goto Sigma_Exit;
}
}
if (code_seen('L') || code_seen('l') ) {
n_legs = code_value();
if ( n_legs==1 )
n_legs = 2;
if ( n_legs<0 || n_legs>15 ) {
SERIAL_PROTOCOLPGM("?Specified number of legs in movement not plausable.\n");
goto Sigma_Exit;
}
}
//
// Do all the preliminary setup work. First raise the probe.
//
st_synchronize();
plan_bed_level_matrix.set_to_identity();
plan_buffer_line( X_current, Y_current, Z_start_location,
ext_position,
homing_feedrate[Z_AXIS]/60,
active_extruder);
st_synchronize();
//
// Now get everything to the specified probe point So we can safely do a probe to
// get us close to the bed. If the Z-Axis is far from the bed, we don't want to
// use that as a starting point for each probe.
//
if (verbose_level > 2)
SERIAL_PROTOCOL("Positioning probe for the test.\n");
plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location,
ext_position,
homing_feedrate[X_AXIS]/60,
active_extruder);
st_synchronize();
current_position[X_AXIS] = X_current = st_get_position_mm(X_AXIS);
current_position[Y_AXIS] = Y_current = st_get_position_mm(Y_AXIS);
current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS);
current_position[E_AXIS] = ext_position = st_get_position_mm(E_AXIS);
//
// OK, do the inital probe to get us close to the bed.
// Then retrace the right amount and use that in subsequent probes
//
engage_z_probe();
setup_for_endstop_move();
run_z_probe();
current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS);
Z_start_location = st_get_position_mm(Z_AXIS) + Z_RAISE_BEFORE_PROBING;
plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location,
ext_position,
homing_feedrate[X_AXIS]/60,
active_extruder);
st_synchronize();
current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS);
if (engage_probe_for_each_reading)
retract_z_probe();
for( n=0; n<n_samples; n++) {
do_blocking_move_to( X_probe_location, Y_probe_location, Z_start_location); // Make sure we are at the probe location
if ( n_legs) {
double radius=0.0, theta=0.0, x_sweep, y_sweep;
int rotational_direction, l;
rotational_direction = (unsigned long) millis() & 0x0001; // clockwise or counter clockwise
radius = (unsigned long) millis() % (long) (X_MAX_LENGTH/4); // limit how far out to go
theta = (float) ((unsigned long) millis() % (long) 360) / (360./(2*3.1415926)); // turn into radians
//SERIAL_ECHOPAIR("starting radius: ",radius);
//SERIAL_ECHOPAIR(" theta: ",theta);
//SERIAL_ECHOPAIR(" direction: ",rotational_direction);
//SERIAL_PROTOCOLLNPGM("");
for( l=0; l<n_legs-1; l++) {
if (rotational_direction==1)
theta += (float) ((unsigned long) millis() % (long) 20) / (360.0/(2*3.1415926)); // turn into radians
else
theta -= (float) ((unsigned long) millis() % (long) 20) / (360.0/(2*3.1415926)); // turn into radians
radius += (float) ( ((long) ((unsigned long) millis() % (long) 10)) - 5);
if ( radius<0.0 )
radius = -radius;
X_current = X_probe_location + cos(theta) * radius;
Y_current = Y_probe_location + sin(theta) * radius;
if ( X_current<X_MIN_POS) // Make sure our X & Y are sane
X_current = X_MIN_POS;
if ( X_current>X_MAX_POS)
X_current = X_MAX_POS;
if ( Y_current<Y_MIN_POS) // Make sure our X & Y are sane
Y_current = Y_MIN_POS;
if ( Y_current>Y_MAX_POS)
Y_current = Y_MAX_POS;
if (verbose_level>3 ) {
SERIAL_ECHOPAIR("x: ", X_current);
SERIAL_ECHOPAIR("y: ", Y_current);
SERIAL_PROTOCOLLNPGM("");
}
do_blocking_move_to( X_current, Y_current, Z_current );
}
do_blocking_move_to( X_probe_location, Y_probe_location, Z_start_location); // Go back to the probe location
}
if (engage_probe_for_each_reading) {
engage_z_probe();
delay(1000);
}
setup_for_endstop_move();
run_z_probe();
sample_set[n] = current_position[Z_AXIS];
//
// Get the current mean for the data points we have so far
//
sum=0.0;
for( j=0; j<=n; j++) {
sum = sum + sample_set[j];
}
mean = sum / (double (n+1));
//
// Now, use that mean to calculate the standard deviation for the
// data points we have so far
//
sum=0.0;
for( j=0; j<=n; j++) {
sum = sum + (sample_set[j]-mean) * (sample_set[j]-mean);
}
sigma = sqrt( sum / (double (n+1)) );
if (verbose_level > 1) {
SERIAL_PROTOCOL(n+1);
SERIAL_PROTOCOL(" of ");
SERIAL_PROTOCOL(n_samples);
SERIAL_PROTOCOLPGM(" z: ");
SERIAL_PROTOCOL_F(current_position[Z_AXIS], 6);
}
if (verbose_level > 2) {
SERIAL_PROTOCOL(" mean: ");
SERIAL_PROTOCOL_F(mean,6);
SERIAL_PROTOCOL(" sigma: ");
SERIAL_PROTOCOL_F(sigma,6);
}
if (verbose_level > 0)
SERIAL_PROTOCOLPGM("\n");
plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location,
current_position[E_AXIS], homing_feedrate[Z_AXIS]/60, active_extruder);
st_synchronize();
if (engage_probe_for_each_reading) {
retract_z_probe();
delay(1000);
}
}
retract_z_probe();
delay(1000);
clean_up_after_endstop_move();
// enable_endstops(true);
if (verbose_level > 0) {
SERIAL_PROTOCOLPGM("Mean: ");
SERIAL_PROTOCOL_F(mean, 6);
SERIAL_PROTOCOLPGM("\n");
}
SERIAL_PROTOCOLPGM("Standard Deviation: ");
SERIAL_PROTOCOL_F(sigma, 6);
SERIAL_PROTOCOLPGM("\n\n");
Sigma_Exit:
break;
}
#endif // ENABLE_AUTO_BED_LEVELING
Ok, I substituted the code you provided in the last post with the commented out code for all of M48. It compiled and ran (I just issued an M48 with no arguments right after a G28), but it immediately tries to go off the printer radius without descending (the front two of the three delta steppers move, but not the rear one - for a delta to descend, all three motors must move together.) In the monitor log, it printed
"M48 Z-Probe Repeatablility test Version 1.85
Starting Probe: 434.0500, Ending Probe"
I will have to look at the code closer to see if there is a translation somewhere in it or what it calls to do the transform of regular cartesian to delta coordinates, but that 434.05 number looks wrong to me. Right after a G28, the nozzle on my machine is about 192mm above the bed (Z = 192), so I'll have to look to see where the 434 number is coming from.
G28 and M119 all look good, and I can print perfectly with the machine all day long.
Perhaps I a bit confused as to the input arguments. Here are what I believe to be the relavant setting in Configuration.h:
#define X_PROBE_OFFSET_FROM_EXTRUDER 0
#define Y_PROBE_OFFSET_FROM_EXTRUDER -19
#define Z_PROBE_OFFSET_FROM_EXTRUDER 23 //-18.48 // Increase this if the first layer is too thin (remember: it's a negative number so increase means closer to zero).
#define Z_RAISE_BEFORE_HOMING 20.0 // (in mm) Raise Z before homing (G28) for Probe Clearance.
// Be sure you have this distance over your Z_MAX_POS in case
#define XY_TRAVEL_SPEED 1000 // X and Y axis travel speed between probes, in mm/min
#define Z_RAISE_BEFORE_PROBING 7.0 //How much the extruder will be raised before traveling to the first probing point.
#define Z_RAISE_BETWEEN_PROBINGS 7.0 //How much the extruder will be raised when traveling from between next probing points
Some of these might be for G29 or G30 as well.
About my probe - its just a snap on microswitch that has the switch arm contact point directly in front of the nozzle (x offset = 0) and a bit to the right (y offset = 19mm) and the switch arm hangs down a bit. I've measured that the switch toggles right at a height of 18.48mm above the position when the nozzle itself is at zero. However, there is about 5mm of distance between where the switch arm just contacts the surface and the switch triggers, so I made the height offset to be 23. (I saw in the code where it should try to go Z-10mm during the probe.)
Are these settings correct?
The comment in the code, "// Be sure you have this distance over your Z_MAX_POS in case" is rather vague and poor english so I am not really sure what is meant by it.
What code base are you using? Can you pull down the Beckdac code and move your settings to that? I know what is in that fork and how things are setup in there. If you move your setting over to that code base it will be much easier to help you get things going.
Beckdac's code is at: https://github.com/beckdac/Marlin
Oh? I didn't expect that. OK... How about we use this repository:
https://github.com/ErikZalm/Marlin
What I'm trying to do is not use the recent code at: https://github.com/MarlinFirmware/Marlin They have made change after change without testing anything and right now the Auto Bed Leveling is sick. So let's try that ErikZalm link and get your stuff going using that.
The code base I am using has specific enhanemments other than M48/G29/G30 I need to use. My understanding is that it's g30 is better in that it takes only a few passes to converge, so I was also hoping to use it.
Thanks for the help, Roxy. I guess I'll just have to work it out what is going on with what I have.
I sure would like to know why they rewrote your m48 code for the latest Marlin pull, though. As it is, there is a lot of code in marlin_main.cpp for this stuff when it seems it could be unified into something much simpler.
Ok, give me a bit to get the Zalm configuration.h updated to my machine. Other than that, the M48, G29, G30 and relavant section of the configuration.h file appears to be the same as what I am running on my verison, with the exception I mentioned before - I've cut off the engage_z_probe() and retract_z_probe() routines to just return right away as I don't need to do that. Could there be something in there that is needed later that is the problem?
You know who PJR is?
I think what you ought to do is leave the engage_z_probe() and retract_z_probe() alone and just assign them to use unused pins. That way everything is behaving the same other than those two functions don't do anything. But with that said, making them null routines really ought to be OK.
Part of the reason to leave the engage_z_probe() and retract_z_probe() alone is there may be other code that assumes a servo is available because you have Auto Bed Leveling. That would be the easiest path to getting everything going. And then when everything is working we can prune the servo out of the picture.
No...
Roxy, I've got a question about how the z position numbers are calculated in your M48 code compared to other commands. I've been battling a problem all day that started with a wire falling off my z-probe. After fixing that, I noticed that the microswitch was slightly tilted and when coming down to the bed, the lever would hit first, but before tripping, the opposite side of the switch would hit the glass and move the arm slightly. I adjusted that and since I haven't been able to get a good print. I've gone around and around adjusting the z probe offset value and storing it in EEPROM, but every time I try to start a print, it's just smashing the filament down on the glass making blobs and wide streaks.
Anyway, what I've noticed is that if my current offset is set to say -10.65, when I run the G29 command, the 4 points it probes list z values close to and around that offset. However, when I run the M48 code, the numbers it reports for each sample are around the 10.24 range. The test comes out very acceptable. I can't see that there's any great fluctuation or problems with the probe, but I'm curious why the numbers are different as that amount of difference looks to be in the ballpark of what might actually get it printing properly again. I'd guess it's about .4mm off.
Bruce
Bruce,
Did you figure this out? I'm having the same issue. G29 results seem to vary quite a bit but M48 results are very consistent and differ from the G29 resutls. And, like you, the difference seems like it would explain my occassional air prints. It seems the two should produce similar measurements. If not, it would be nice to have an explanation as to why.
I'm sorry... I didn't see Bruce's question until just now.
The answer is: "Don't worry about it." The root of the problem is the different GCode commands use different methods to probe the bed. That is slowly getting unified. But because they use different methods, they report some what different values. G28 does its thing using linear move routines. G29 uses the probe_pt() routine and then corrects for Z_PROBE_OFFSET_FROM_EXTRUDER. And M48 is sort of a hybrid of the two.
This is getting corrected, but right now getting the Release Candidate stable and out the door is a higher priority.
If you use G29, don't worry about the G28 numbers. G29 is correcting for the bigger picture. G28 is mostly concerned about making sure the nozzle is within the build space.
And M48 doesn't care about any of that. It just cares that it can accurately measure the location of the probe again and again. It subtracts off what ever the mean of the measured points is and calculates the standard deviation.
Hi Roxy,
It's with great interest that I readed this thread of discuss, and I thank you for the great job and the support you provide.
I constructed a Delta printer with a probe for the Bed Auto Leveling incorporated into the effector, so that the HotEnd's nozzle is the probe. I would be interested in your M48 function, but from what I've read, your code was integrated into the Marlin firmware, but no longer works well since the great upheaval this summer ...
My questions :
- Does the Z_MIN_PROBE_REPEATABILITY_TEST function has to do with your M48 function? If so, how can we setup number of measuring ... ?
- I also read that the M48 function was not available for the Delta because of the gap between the probe and the nozzle could generate impossible calculations (sqtr(zero)). Since in my case the nozzle is the probe, could i override and how?
- last question: G29 function seems to work fine, however the recorded data do not seem to be taken into account when printing. I saw that I was not alone having this problem, but I did not see any solution except to upgrade to Marlin RC3 version ... but I'm already in the RC3 version ... An idea?
Best regards,
Hubert
1) Yes. That controls the ability to do M48 and test how repeatable the Z-Probe is. But the Release Candidates do not support M48 for Deltas.
2) Yes. I did not have a Delta when I wrote the M48 code. I didn't know they use different routines to move the effector. The sqrt() of a negative number is related to trying to move the nozzle off the bed so you can probe the maximum area. Don't worry about that right now.
3) The M48 code is working for Delta's now. But you have to go to the MarlinDev side of the fence and bring up WackerBarth's new development environment. (That is what we expect the Marlin Development Team will be switching too.) You can find it here: https://github.com/Wackerbarth/MarlinDev/tree/Dec26 Look at the Wiki for the complete directions how to get the environment set up. This branch has a lot of Delta stuff fixed. But we are trying to get the Release Candidate to the state it needs to be without adding any thing that doesn't have to be in it.
Hi Roxy,
I took your advice and installed the MarlinDev environment. It works correctly, I can compile with no problem at all.
However, I am a bit confused because this version of the firmware adopts a new method of statement of parameters that the wiki does not explain (https://github.com/MarlinFirmware/Ma...Configurations)
According to what I read, good practices are to define a file of parameters for every type of printer, and to decline sub-configurations for every machine by using the mechanism of inheritance.
My question: Is there a documentation, even has the state of draft somewhere? If not, can you tell me what are the new files of configuration to use (customization.h, FirmwareCustomization.h...) and how to integrate them into the firmware?
Best regards,
Hubert
Richard Wackerbarth is doing the work on this branch. It is my expectation that after we do the next release this will be used as the next official MarlinDev environment with the intention that it will be promoted to Release Candidate status. (Mostly, I'm just trying to say, this isn't wasted effort on your part.)
My suggestion is go to https://github.com/MarlinFirmware/Ma...3Aupdated-desc and start a thread asking for assistance. Please be sure to explain why you are trying to use the branch and that you were requested to use it and ask for assistance at MarlinDev. The problem is I'm just starting to get my head around the new organization myself. I'll help you with what I can, but the changes that it takes to clean up the code are extensive. You will get better and quicker help at MarlinDev.
Hi Roxy,
After six months out I'm back, and I see that the "new" MarlinDev project is closed. . . I guess it was transferred to the Marlin project, but it seems that the organization of the configuration files has changed yet. For example there is no longer the Customization.h files. I can't find any information about this redesign on Wikis. Could you please tell me if this is the old policy configuration that has been rehabilitated?
We have not deleted the MarlinDev repository yet. But it is inactive. The people contributing regularly to Marlin do not want to go down the 'Customization.h' path because it would force them to abandon all of the code forks they have. There are strong arguments on both sides, but the people actually contributing want the code structured the way it is on the MarlinFirmware/Marlin side.
With that said, we have started a Development branch and we do expect to promote RC-6 to RC-7 very soon. And we expect to promote RC-7 to a Stable v1.1.0 release. RC-6 is pretty solid. If you are loading up a new printer, it is a good firmware to load.
It looks like the last Marlin I downloaded and installed to my printer was 1.0.2 in April 2015. When the stable release comes out, do you recommend a clean install, or would I be able to get by with using a diff viewer to copy over any changes?
You really should use a visual diff program to cross your configuration.h and configuration_adv.h file over to the new code base. The reason is a number of options have been combined (and the name changed). And new options have been added. There aren't going to be that many differences, but you want to go through they one by one and make intelligent choices on each difference.
Hi Roxy,
I took your advice and I realized my new configuration based on RC-6 version.
I have a problem with the bed probing. The G30 command works well, the Effector will stop when the probe touch the bed, but the G29 seems not taking into account the state of the probe as the effector continues down.
For information, i tried to use #define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN or Z_MIN_PROBE_ENDSTOP instead, and have exactly the same behaviour
Edit :
All right, i found what's wrong : I forgot to uncomment "#define MECHANICAL_PROBE", now everything works perfectly
Don't feel bad! I always get my probe stuff configured wrong the first time too!
Roxy, when do you expect RC7 to goto Stable?
I am in RC5, but if the time is short I will rather wait for the stable,release.
I'm pretty sure we are not going to promote RC-7 to Stable. We are trying to resolve a Z-Offset issue in RC-7. Once we do that we will start RC-8. And if we don't find any horrible issues in the next 6 or 8 weeks, I think that will be promoted to Stable.