I have a large heavy printbed that had the same problems with dropping unlevel at power off.
Here's how I overcome it:
I grabbed a stepper brake design from thingyverse and modified it for use with a solenoid.
Here is the final result:
I have these on all 3 Z steppers and they are controlled by a cheap arduino nano.
The nano is used as an interface to be able to control the braking exactly how I want.
It looks for a brake control signal that I set up on the Duet 3 board.
By default the brakes are on. When the printer is powered up one of the first commands in config.g is to enable the Z motors. This locks their positions and therefore is now safe to release the brakes without causing any Z movement.
The only downside is that for complete control I have to use my own board reset, e-stop and shutdown macros but this is not a real problem for me.
Visually, I no longer see any Z drop but to be safe after every power up I do one quick bed level
which before the upgrade would have not been enough to level the bed accurately.
Now, I see no bed drop and the bed is guaranteed level within seconds of power up.
Here is what is required:
In config.g:
; Z brake control
M17 Z ; enable Z motors to hold bed position before brake is released
; set up servo brake signal on out5
M950 P5 C"io5.out"
M42 P5 S255 ; brake off
My Macros:
E-Stop:
M42 P5 S0 ; brake on
G4 P500 ; wait 500 milli seconds
M112
Reset:
M42 P5 S0 ; brake on
G4 P500 ; wait 500 milli seconds
M999
shutdown:
; macro to shutdown printer after hot end has cooled down
; carry out some checks first
G10 S0 R0 ; Set active and standby temps to zero to ensure nothing is on standby
M140 S0 ; heated bed heater off
; only shutdown if extruder temperature is below 70
while true
if sensors.analog[1].lastReading > 70 ; if hot end temperature is 70 or above then cool down
M291 P{"Hot end temperature too high, cooling in progress!" } R"Power Management" S1 T0
;break ; if not true, go to next command
if sensors.analog[1].lastReading < 68
M291 P{"Hot end temperature < 68, shutting down now" } R"Power Management" S0 T4
M42 P5 S0 ; apply Z brakes
G4 S2 ; wait 2 seconds
M81 ; atx power off
Arduino code:
#include <Servo.h>
//Define duet output pin
#define inPin 12
#define PUSHED HIGH // look for active high
byte lastState;
unsigned long startMillis; // time variable
Servo servo1;
Servo servo2;
Servo servo3;
void setup()
{
servo1.attach(3); // servo 1
servo2.attach(4); // servo 2
servo3.attach(5); // servo 3
pinMode(inPin, INPUT_PULLUP);
//keep brake on at power up (brake arm is at 90 degrees when in off position!)
servo1.write(0); // brake on
servo2.write(0);
servo3.write(0);
delay(10000); // delay for duet initialisation
servo1.write(100); // brake off
servo2.write(100);
servo3.write(100);
delay(10000);
}
// duet in control from here onwards
void loop()
{
byte thisState = digitalRead(inPin);
//look for changed state?
if (lastState != thisState)
{
//update to the new state
lastState = thisState;
//record time
startMillis = millis();
}
//check for changed state
// if (lastState == PUSHED) {
// inPin state must have changed for >= 2 seconds to eliminate false triggers
if (lastState == PUSHED && millis() - startMillis >= 2000UL)
{
servo1.write(100); // brake off if input high
servo2.write(100);
servo3.write(100);
delay(1000);
}
else
{
servo1.write(0); // brake on if input low
servo2.write(0);
servo3.write(0);
delay(1000);
}
}