
Implemented F, H and R parameters to M106 command. The second fan output on a Duet 0.8.5 now defaults to being a thermostatic fan at power up. Improved speed of file upload to SD card G32 is now allowed if the printer has not been homed, if there is a bed.g file G30 commands are no longer allowed on a delta that has not been homed M572 parameter P (drive number) replaced by parameter D (extruder number) File info requests are now processed in stages to reduce impact on printing (thanks chrishamm) Use latest network stack and webserver modules from chrishamm (thanks chrishamm) Added Roland mill support (thanks RRP/chrishamm) Added S parameter (idle timeout) to M18 ans M84 commands (thanks chrishamm) Moved I/O pin assignments to separate Pins.h file to more easily support alternative hardware (thanks dnewman) Bug fix: filament usage and % print complete figures were incorrect when absolute extruder coordinates were used Bug fix: file-based print estimate was occasionally returned as 'inf' which caused the web interface to disconnect Bug fix: M666 now flags all towers as not homed Bug fixes to extruder pressure compensation (M572 command).
199 lines
12 KiB
C++
199 lines
12 KiB
C++
/*
|
|
* Move.h
|
|
*
|
|
* Created on: 7 Dec 2014
|
|
* Author: David
|
|
*/
|
|
|
|
#ifndef MOVE_H_
|
|
#define MOVE_H_
|
|
|
|
#include "DDA.h"
|
|
#include "Matrix.h"
|
|
#include "DeltaParameters.h"
|
|
#include "DeltaProbe.h"
|
|
|
|
const unsigned int DdaRingLength = 20;
|
|
|
|
enum PointCoordinateSet
|
|
{
|
|
unset = 0,
|
|
xSet = 1,
|
|
ySet = 2,
|
|
zSet = 4,
|
|
xyCorrected = 8,
|
|
probeError = 16
|
|
};
|
|
|
|
/**
|
|
* This is the master movement class. It controls all movement in the machine.
|
|
*/
|
|
class Move
|
|
{
|
|
public:
|
|
|
|
Move(Platform* p, GCodes* g);
|
|
void Init(); // Start me up
|
|
void Spin(); // Called in a tight loop to keep the class going
|
|
void Exit(); // Shut down
|
|
void GetCurrentUserPosition(float m[DRIVES + 1], uint8_t moveType) const; // Return the position (after all queued moves have been executed) in transformed coords
|
|
int32_t GetEndPoint(size_t drive) const { return liveEndPoints[drive]; } // Get the current position of a motor
|
|
void LiveCoordinates(float m[DRIVES]); // Gives the last point at the end of the last complete DDA transformed to user coords
|
|
void Interrupt(); // The hardware's (i.e. platform's) interrupt should call this.
|
|
void InterruptTime(); // Test function - not used
|
|
bool AllMovesAreFinished(); // Is the look-ahead ring empty? Stops more moves being added as well.
|
|
void ResumeMoving(); // Allow moves to be added after a call to AllMovesAreFinished()
|
|
void DoLookAhead(); // Run the look-ahead procedure
|
|
void HitLowStop(size_t axis, DDA* hitDDA); // What to do when a low endstop is hit
|
|
void HitHighStop(size_t axis, DDA* hitDDA); // What to do when a high endstop is hit
|
|
void ZProbeTriggered(DDA* hitDDA); // What to do when a the Z probe is triggered
|
|
void SetPositions(const float move[DRIVES]); // Force the coordinates to be these
|
|
void SetFeedrate(float feedRate); // Sometimes we want to override the feed rate
|
|
void SetLiveCoordinates(const float coords[DRIVES]); // Force the live coordinates (see above) to be these
|
|
void SetXBedProbePoint(size_t index, float x); // Record the X coordinate of a probe point
|
|
void SetYBedProbePoint(size_t index, float y); // Record the Y coordinate of a probe point
|
|
void SetZBedProbePoint(size_t index, float z, bool wasXyCorrected, bool wasError); // Record the Z coordinate of a probe point
|
|
float XBedProbePoint(size_t index) const; // Get the X coordinate of a probe point
|
|
float YBedProbePoint(size_t index) const; // Get the Y coordinate of a probe point
|
|
float ZBedProbePoint(size_t index)const ; // Get the Z coordinate of a probe point
|
|
size_t NumberOfProbePoints() const; // How many points to probe have been set? 0 if incomplete
|
|
size_t NumberOfXYProbePoints() const; // How many XY coordinates of probe points have been set (Zs may not have been probed yet)
|
|
bool AllProbeCoordinatesSet(int index) const; // XY, and Z all set for this one?
|
|
bool XYProbeCoordinatesSet(int index) const; // Just XY set for this one?
|
|
void FinishedBedProbing(int sParam, StringRef& reply); // Calibrate or set the bed equation after probing
|
|
float SecondDegreeTransformZ(float x, float y) const; // Used for second degree bed equation
|
|
void SetAxisCompensation(int8_t axis, float tangent); // Set an axis-pair compensation angle
|
|
float AxisCompensation(int8_t axis) const; // The tangent value
|
|
void SetIdentityTransform(); // Cancel the bed equation; does not reset axis angle compensation
|
|
void Transform(float move[]) const; // Take a position and apply the bed and the axis-angle compensations
|
|
void InverseTransform(float move[]) const; // Go from a transformed point back to user coordinates
|
|
void Diagnostics(); // Report useful stuff
|
|
|
|
const DeltaParameters& GetDeltaParams() const { return deltaParams; }
|
|
DeltaParameters& AccessDeltaParams() { return deltaParams; }
|
|
bool IsDeltaMode() const { return deltaParams.IsDeltaMode(); }
|
|
const char* GetGeometryString() const;
|
|
|
|
int GetCoreXYMode() const { return coreXYMode; }
|
|
void SetCoreXYMode(int mode) { coreXYMode = mode; }
|
|
float GetCoreAxisFactor(size_t axis) const { return axisFactors[axis]; }
|
|
void setCoreAxisFactor(size_t axis, float f) { axisFactors[axis] = f; }
|
|
bool IsCoreXYAxis(size_t axis) const; // return true if the specified axis shares its motors with another
|
|
|
|
void CurrentMoveCompleted(); // signals that the current move has just been completed
|
|
bool StartNextMove(uint32_t startTime); // start the next move, returning true if Step() needs to be called immediately
|
|
void MotorTransform(const float machinePos[AXES], int32_t motorPos[AXES]) const; // Convert Cartesian coordinates to delta motor coordinates
|
|
float MotorFactor(size_t drive, const float directionVector[]) const; // Calculate the movement fraction for a single axis motor of a Cartesian or CoreXY printer
|
|
void MachineToEndPoint(const int32_t motorPos[], float machinePos[], size_t numDrives) const; // Convert motor coordinates to machine coordinates
|
|
void EndPointToMachine(const float coords[], int32_t ep[], size_t numDrives) const;
|
|
|
|
float IdleTimeout() const { return idleTimeout; } // Returns the idle timeout in seconds
|
|
void SetIdleTimeout(float timeout) { idleTimeout = timeout; } // Set the idle timeout in seconds
|
|
|
|
void Simulate(bool sim); // Enter or leave simulation mode
|
|
float GetSimulationTime() const { return simulationTime; } // Get the accumulated simulation time
|
|
void PrintCurrentDda() const; // For debugging
|
|
|
|
FilePosition PausePrint(float positions[DRIVES+1]); // Pause the print as soon as we can
|
|
bool NoLiveMovement() const; // Is a move running, or are there any queued?
|
|
|
|
int DoDeltaProbe(float frequency, float amplitude, float rate, float distance);
|
|
|
|
static int32_t MotorEndPointToMachine(size_t drive, float coord); // Convert a single motor position to number of steps
|
|
static float MotorEndpointToPosition(int32_t endpoint, size_t drive); // Convert number of motor steps to motor position
|
|
|
|
private:
|
|
|
|
enum class IdleState : uint8_t { idle, busy, timing };
|
|
|
|
void SetProbedBedEquation(size_t numPoints, StringRef& reply); // When we have a full set of probed points, work out the bed's equation
|
|
void DoDeltaCalibration(size_t numPoints, StringRef& reply);
|
|
void BedTransform(float move[AXES]) const; // Take a position and apply the bed compensations
|
|
void GetCurrentMachinePosition(float m[DRIVES + 1], bool disableMotorMapping) const; // Get the current position and feedrate in untransformed coords
|
|
void InverseBedTransform(float move[AXES]) const; // Go from a bed-transformed point back to user coordinates
|
|
void AxisTransform(float move[AXES]) const; // Take a position and apply the axis-angle compensations
|
|
void InverseAxisTransform(float move[AXES]) const; // Go from an axis transformed point back to user coordinates
|
|
void BarycentricCoordinates(size_t p0, size_t p1, // Compute the barycentric coordinates of a point in a triangle
|
|
size_t p2, float x, float y, float& l1, // (see http://en.wikipedia.org/wiki/Barycentric_coordinate_system).
|
|
float& l2, float& l3) const;
|
|
float TriangleZ(float x, float y) const; // Interpolate onto a triangular grid
|
|
void AdjustDeltaParameters(const float v[], size_t numFactors); // Perform delta adjustment
|
|
void JustHomed(size_t axis, float hitPoint, DDA* hitDDA); // deal with setting positions after a drive has been homed
|
|
|
|
static void PrintMatrix(const char* s, const MathMatrix<float>& m, size_t numRows = 0, size_t maxCols = 0); // for debugging
|
|
static void PrintVector(const char *s, const float *v, size_t numElems); // for debugging
|
|
|
|
bool DDARingAdd(); // Add a processed look-ahead entry to the DDA ring
|
|
DDA* DDARingGet(); // Get the next DDA ring entry to be run
|
|
bool DDARingEmpty() const; // Anything there?
|
|
|
|
DDA* volatile currentDda;
|
|
DDA* ddaRingAddPointer;
|
|
DDA* volatile ddaRingGetPointer;
|
|
DDA* ddaRingCheckPointer;
|
|
|
|
bool addNoMoreMoves; // If true, allow no more moves to be added to the look-ahead
|
|
bool active; // Are we live and running?
|
|
bool simulating; // Are we simulating, or really printing?
|
|
unsigned int idleCount; // The number of times Spin was called and had no new moves to process
|
|
float simulationTime; // Print time since we started simulating
|
|
float currentFeedrate; // Err... the current feed rate...
|
|
volatile float liveCoordinates[DRIVES]; // The endpoint that the machine moved to in the last completed move
|
|
volatile bool liveCoordinatesValid; // True if the XYZ live coordinates are reliable (the extruder ones always are)
|
|
volatile int32_t liveEndPoints[DRIVES]; // The XYZ endpoints of the last completed move in motor coordinates
|
|
|
|
float xBedProbePoints[MAX_PROBE_POINTS]; // The X coordinates of the points on the bed at which to probe
|
|
float yBedProbePoints[MAX_PROBE_POINTS]; // The Y coordinates of the points on the bed at which to probe
|
|
float zBedProbePoints[MAX_PROBE_POINTS]; // The Z coordinates of the points on the bed at which to probe
|
|
float baryXBedProbePoints[5]; // The X coordinates of the triangle corner points
|
|
float baryYBedProbePoints[5]; // The Y coordinates of the triangle corner points
|
|
float baryZBedProbePoints[5]; // The Z coordinates of the triangle corner points
|
|
uint8_t probePointSet[MAX_PROBE_POINTS]; // Has the XY of this point been set? Has the Z been probed?
|
|
float aX, aY, aC; // Bed plane explicit equation z' = z + aX*x + aY*y + aC
|
|
float tanXY, tanYZ, tanXZ; // Axis compensation - 90 degrees + angle gives angle between axes
|
|
int numBedCompensationPoints; // The number of points we are actually using for bed compensation, 0 means identity bed transform
|
|
float xRectangle, yRectangle; // The side lengths of the rectangle used for second-degree bed compensation
|
|
|
|
float idleTimeout; // How long we wait with no activity before we reduce motor currents to idle
|
|
float lastMoveTime; // The approximate time at which the last move was completed, or 0
|
|
float longWait; // A long time for things that need to be done occasionally
|
|
IdleState iState; // whether the idle timer is active
|
|
|
|
DeltaParameters deltaParams; // Information about the delta parameters of this machine
|
|
DeltaProbe deltaProbe; // Delta probing state
|
|
uint32_t deltaProbingStartTime;
|
|
bool deltaProbing;
|
|
int coreXYMode; // 0 = Cartesian, 1 = CoreXY, 2 = CoreXZ, 3 = CoreYZ
|
|
float axisFactors[AXES]; // How much further the motors need to move for each axis movement, on a CoreXY/CoreXZ/CoreYZ machine
|
|
unsigned int stepErrors; // count of step errors, for diagnostics
|
|
};
|
|
|
|
//******************************************************************************************************
|
|
|
|
inline bool Move::DDARingEmpty() const
|
|
{
|
|
return ddaRingGetPointer == ddaRingAddPointer;
|
|
}
|
|
|
|
inline bool Move::NoLiveMovement() const
|
|
{
|
|
return DDARingEmpty() && currentDda == nullptr; // must test currentDda and DDARingEmpty *in this order* !
|
|
}
|
|
|
|
// To wait until all the current moves in the buffers are
|
|
// complete, call this function repeatedly and wait for it to
|
|
// return true. Then do whatever you wanted to do after all
|
|
// current moves have finished. THEN CALL THE ResumeMoving() FUNCTION
|
|
// OTHERWISE NOTHING MORE WILL EVER HAPPEN.
|
|
inline bool Move::AllMovesAreFinished()
|
|
{
|
|
addNoMoreMoves = true;
|
|
return NoLiveMovement();
|
|
}
|
|
|
|
inline void Move::ResumeMoving()
|
|
{
|
|
addNoMoreMoves = false;
|
|
}
|
|
|
|
#endif /* MOVE_H_ */
|