
Support concurrenrt execution of commands form different channels M143 now supports individual temperature limits per heater Fixed issue with dely of up to 2 seconds when switching Duet WiFi heater channel 3 to servo mode When enable polarity is set using the M569 R parameter, disable the corresponding drive Add exdperimental S99 option on G1 command to log probe changes (Duet WiFi only)
165 lines
6.3 KiB
C++
165 lines
6.3 KiB
C++
/*
|
|
* DriveMovement.h
|
|
*
|
|
* Created on: 17 Jan 2015
|
|
* Author: David
|
|
*/
|
|
|
|
#ifndef DRIVEMOVEMENT_H_
|
|
#define DRIVEMOVEMENT_H_
|
|
|
|
class DDA;
|
|
|
|
// Struct for passing parameters to the DriveMovement Prepare methods
|
|
struct PrepParams
|
|
{
|
|
float decelStartDistance;
|
|
uint32_t startSpeedTimesCdivA;
|
|
uint32_t topSpeedTimesCdivA;
|
|
uint32_t decelStartClocks;
|
|
uint32_t topSpeedTimesCdivAPlusDecelStartClocks;
|
|
uint32_t accelClocksMinusAccelDistanceTimesCdivTopSpeed;
|
|
float compFactor;
|
|
};
|
|
|
|
enum class DMState : uint8_t
|
|
{
|
|
idle = 0,
|
|
moving = 1,
|
|
stepError = 2
|
|
};
|
|
|
|
// This class describes a single movement of one drive
|
|
class DriveMovement
|
|
{
|
|
public:
|
|
bool CalcNextStepTimeCartesian(const DDA &dda, bool live);
|
|
bool CalcNextStepTimeDelta(const DDA &dda, bool live);
|
|
void PrepareCartesianAxis(const DDA& dda, const PrepParams& params);
|
|
void PrepareDeltaAxis(const DDA& dda, const PrepParams& params);
|
|
void PrepareExtruder(const DDA& dda, const PrepParams& params, bool doCompensation);
|
|
void ReduceSpeed(const DDA& dda, float inverseSpeedFactor);
|
|
void DebugPrint(char c, bool withDelta) const;
|
|
int32_t GetNetStepsLeft() const;
|
|
|
|
private:
|
|
bool CalcNextStepTimeCartesianFull(const DDA &dda, bool live);
|
|
bool CalcNextStepTimeDeltaFull(const DDA &dda, bool live);
|
|
|
|
public:
|
|
// Parameters common to Cartesian, delta and extruder moves
|
|
|
|
// The following only need to be stored per-drive if we are supporting pressure advance
|
|
uint64_t twoDistanceToStopTimesCsquaredDivA;
|
|
uint32_t startSpeedTimesCdivA;
|
|
int32_t accelClocksMinusAccelDistanceTimesCdivTopSpeed; // this one can be negative
|
|
uint32_t topSpeedTimesCdivAPlusDecelStartClocks;
|
|
|
|
// These values don't depend on how the move is executed, so are set by Init()
|
|
uint32_t totalSteps; // total number of steps for this move
|
|
uint8_t drive; // the drive that this DM controls
|
|
DMState state; // whether this is active or not
|
|
bool direction; // true=forwards, false=backwards
|
|
uint8_t stepsTillRecalc; // how soon we need to recalculate
|
|
|
|
// These values change as the step is executed
|
|
uint32_t nextStep; // number of steps already done
|
|
uint32_t reverseStartStep; // the step number for which we need to reverse direction due to pressure advance or delta movement
|
|
uint32_t nextStepTime; // how many clocks after the start of this move the next step is due
|
|
uint32_t stepInterval; // how many clocks between steps
|
|
DriveMovement *nextDM; // link to next DM that needs a step
|
|
|
|
// Parameters unique to a style of move (Cartesian, delta or extruder). Currently, extruders and Cartesian moves use the same parameters.
|
|
union MoveParams
|
|
{
|
|
struct CartesianParameters // Parameters for Cartesian and extruder movement, including extruder pressure advance
|
|
{
|
|
// The following don't depend on how the move is executed, so they could be set up in Init()
|
|
uint64_t twoCsquaredTimesMmPerStepDivA; // 2 * clock^2 * mmPerStepInHyperCuboidSpace / acceleration
|
|
|
|
// The following depend on how the move is executed, so they must be set up in Prepare()
|
|
uint32_t accelStopStep; // the first step number at which we are no longer accelerating
|
|
uint32_t decelStartStep; // the first step number at which we are decelerating
|
|
uint32_t mmPerStepTimesCdivtopSpeed; // mmPerStepInHyperCuboidSpace * clock / topSpeed
|
|
|
|
// The following only need to be stored per-drive if we are supporting pressure advance
|
|
int64_t fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA; // this one can be negative
|
|
} cart;
|
|
|
|
struct DeltaParameters // Parameters for delta movement
|
|
{
|
|
// The following don't depend on how the move is executed, so they can be set up in Init
|
|
int64_t dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared;
|
|
int32_t hmz0sK; // the starting step position less the starting Z height, multiplied by the Z movement fraction and K (can go negative)
|
|
int32_t minusAaPlusBbTimesKs;
|
|
uint32_t twoCsquaredTimesMmPerStepDivAK; // this could be stored in the DDA if all towers use the same steps/mm
|
|
|
|
// The following depend on how the move is executed, so they must be set up in Prepare()
|
|
uint32_t accelStopDsK;
|
|
uint32_t decelStartDsK;
|
|
uint32_t mmPerStepTimesCdivtopSpeedK;
|
|
} delta;
|
|
} mp;
|
|
|
|
static const uint32_t NoStepTime = 0xFFFFFFFF; // value to indicate that no further steps are needed when calculating the next step time
|
|
static const uint32_t K1 = 1024; // a power of 2 used to multiply the value mmPerStepTimesCdivtopSpeed to reduce rounding errors
|
|
static const uint32_t K2 = 512; // a power of 2 used in delta calculations to reduce rounding errors (but too large makes things worse)
|
|
static const int32_t Kc = 1024 * 1024; // a power of 2 for scaling the Z movement fraction
|
|
};
|
|
|
|
// Calculate and store the time since the start of the move when the next step for the specified DriveMovement is due.
|
|
// Return true if there are more steps to do.
|
|
// This is also used for extruders on delta machines.
|
|
// We inline this part to speed things up when we are doing double/quad/octal stepping.
|
|
inline bool DriveMovement::CalcNextStepTimeCartesian(const DDA &dda, bool live)
|
|
{
|
|
if (nextStep < totalSteps)
|
|
{
|
|
++nextStep;
|
|
if (stepsTillRecalc != 0)
|
|
{
|
|
--stepsTillRecalc; // we are doing double/quad/octal stepping
|
|
return true;
|
|
}
|
|
return CalcNextStepTimeCartesianFull(dda, live);
|
|
}
|
|
|
|
state = DMState::idle;
|
|
return false;
|
|
}
|
|
|
|
// Calculate the time since the start of the move when the next step for the specified DriveMovement is due
|
|
// Return true if there are more steps to do
|
|
inline bool DriveMovement::CalcNextStepTimeDelta(const DDA &dda, bool live)
|
|
{
|
|
if (nextStep < totalSteps)
|
|
{
|
|
++nextStep;
|
|
if (stepsTillRecalc != 0)
|
|
{
|
|
--stepsTillRecalc; // we are doing double or quad stepping
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return CalcNextStepTimeDeltaFull(dda, live);
|
|
}
|
|
}
|
|
|
|
state = DMState::idle;
|
|
return false;
|
|
}
|
|
|
|
// Return the number of net steps left for the move in the forwards direction.
|
|
inline int32_t DriveMovement::GetNetStepsLeft() const
|
|
{
|
|
const int32_t netStepsLeft =
|
|
( (nextStep >= reverseStartStep || reverseStartStep >= totalSteps)
|
|
? totalSteps // no reverse due, or we have already reversed
|
|
: 2 * reverseStartStep - totalSteps // we have yet to reverse
|
|
)
|
|
- nextStep + 1;
|
|
return (direction) ? netStepsLeft : -netStepsLeft;
|
|
}
|
|
|
|
#endif /* DRIVEMOVEMENT_H_ */
|