The bed probing in action!
My Kossel, which I have jokingly named “Screw Loose”, left a lot to be desired when I built it. One of the major problems I had was print adhesion- or lack thereof. Even with a heated build plate and kapton, the printer had trouble with peeling and plain not sticking to the bed. I learned what the problem was with a simple test- I went to z0 x0 y0 and moved the head around. On one side of the bed, the head touched the plate. On the other side, it moved away from the plate.
After some searching (circa late 2015), I discovered that there were no RAMPS compatible firmwares that had bed tilt compensation for the Kossel, even though . I am not sure why, and I think since then this has been rectified in a fork of the marlin firmware.
Instead of trying to have the printer compensate based on readings, I decided to take the mechanical approach of actually making the bed flat to the plane of motion of the head. The first thing that had to be changed was how the bed was mounted to the frame of the printer- as it was designed, it just bolted straight on with no adjustment, which was a bad decision because it almost guarantees that the build surface will be at an angle.
Making the bed adjustable was actually pretty easy. I put a long, steel 4-40 screw through the original mounting points, and fixed it to the frame with a nut, creating a “stud”. Using what I had on hand, I made some thumbscrews by laser cutting acrylic and putting it around hex nuts. This let me easily adjust the bed up and down at the three points it attaches to the frame.
The next step was to set up conductive probing. I know people have gotten good results with the servo+microswitch, but I after using a renishaw probing system I just cant deal with how floppy it looks, nevermind the extra wire routing. Conductive probing is actually really easy- I made the mistake of thinking I would have to write some software and started writing my own M code commands, but its actually a hardware solution.
The way bed probing is normally done on the kossel is with a switch mounted on a servo, which is mounted to the print head. This gets wired to an endstop header on the RAMPS board. Each endstop has three pins- ground, 5v, and signal. In order to set up conductive bed leveling, all I had to do was run a wire from the bed to ground, and add a pull up to D18, the pin connected to the “signal” of the endstop header I used. The code in question is here:
float z_probe() { feedrate = homing_feedrate[X_AXIS]; prepare_move_raw(); st_synchronize(); enable_endstops(true); //Turn endstops ON! float start_z = current_position[Z_AXIS]; long start_steps = st_get_position(Z_AXIS); feedrate = homing_feedrate[Z_AXIS]/7; //Make the speed slow destination[Z_AXIS] = -20; //plan to crash into the bed on purpose prepare_move_raw(); st_synchronize(); //Actually execute crash move endstops_hit_on_purpose(); //We crashed into the bed on purpose
Before trying this, it is critical to make sure that the bed and head are clean, and that when they touch you actually trigger the endstop. If the endstop is not triggered, the printer will do its best to drive the print head through the bed, which will leave a dent- I know this from experience. It’s always a good idea to implement a command like my M430 command in marlin_main.cpp to make sure it is working before running g29 (bed probing).
case 430: //M430 SERIAL_PROTOCOLPGM("M430: EC PROBE STATUS"); SERIAL_PROTOCOL(digitalRead(18)); SERIAL_PROTOCOLLN(""); break;
This snippet lets you know that everything is working by manually moving the head into contact with the bed, and checking to see if D18 changes from high to low. It it does not change, the the endstop is not being detected and the printer will try to destroy itself- which is bad.
Once everything is working, G29 should probe the bed, and the head should gently “kiss” the bed in a few locations and spit out a map like this:
21:40:47.704 : 0.000 0.000 -0.400 -0.438 -0.400 0.000 0.000
21:40:53.881 : 0.000 -0.337 -0.400 -0.375 -0.387 -0.438 0.000
21:41:02.489 : -0.375 -0.475 -0.400 -0.375 -0.388 -0.400 -0.413
21:41:11.061 : -0.350 -0.413 -0.338 -0.363 -0.400 -0.388 -0.375
21:41:19.624 : -0.312 -0.475 -0.400 -0.388 -0.388 -0.488 -0.388
21:41:25.760 : 0.000 -0.438 -0.375 -0.350 -0.400 -0.313 0.000
21:41:29.438 : 0.000 0.000 -0.350 -0.363 -0.313 0.000 0.000
After some adjusting, it should be possible to get all the numbers really close- as you can see in this printout. The diameter of the “grid” for these points was ~100mm, and all the points are within about .13 mm, or about .005″, which is pretty good. NB that there are zeroes in all the corners- with stock firmware, you will have bogus numbers there. It is easy to change that to setting them to zero, as seen here (note to self: use git in future):
// For unprobed positions just set to zero if (abs(y) >= 3) { bed_level[1][y+3] = 0; bed_level[5][y+3] = 0; } if (abs(y) >=2) { bed_level[0][y+3] = 0; bed_level[6][y+3] = 0; }
After this, I easily made some decent prints, since it all the layers were even, and the print head never crashed into the plastic! I highly recommend leveling the bed of your kossel if you have one.