This repository has been archived on 2025-02-01. You can view files and clone it, but cannot push or open issues or pull requests.
reprapfirmware-dc42/DeltaParameters.cpp
David Crocker bb8a2c3ef7 Version 1.09b
Z axis min and max limits are now enforced if the axes have been homed
M665 command now shows the re-calculated delta radius and tower offsets
after auto-calibration
Initial and final RMS errors are now shown after delta auto-calibration
Pause/resume now mostly works when absolute extruder coordinates are
used
Doubled the maximum length of the SD card file listing that can be sent
to PanelDue
Implemented zpl's Network and PrintMonitor changes including M404
(thanks, zpl)
Increased default maximum instantaneous speed changes
Bug fix:: if M226 was used to pause the print, the resume coordinates
were not set up correctly
Bug fix: when changing the travel direction, the head was sometimes
slowed down more than necessary
Bug fix: warm-up time was not shown correctly in DuetWebControl
Bug fix: extruder drive positions were always shown as 0.0 in
DuetWebControl
Bug fix: incorrect PID parameters were shown in response to M301
Replaced old web interface files on SD card by DuetWebControl
Modified all resume.g files to set the speed when moving to the paused
head coordinates
2015-06-14 20:15:36 +01:00

272 lines
8.1 KiB
C++

/*
* DeltaParameters.cpp
*
* Created on: 20 Apr 2015
* Author: David
*/
#include "RepRapFirmware.h"
void DeltaParameters::Init()
{
deltaMode = false;
diagonal = 0.0;
radius = 0.0;
printRadius = defaultPrintRadius;
homedHeight = defaultDeltaHomedHeight;
isEquilateral = true;
for (size_t axis = 0; axis < AXES; ++axis)
{
endstopAdjustments[axis] = 0.0;
towerX[axis] = towerY[axis] = 0.0;
}
}
float DeltaParameters::GetRadius() const
{
if (isEquilateral)
{
return radius;
}
else
{
// Towers have been moved so we need to compute the effective radius
const float x1 = towerX[1] - towerX[0], x2 = towerX[2] - towerX[0], y1 = towerY[1] - towerY[0], y2 = towerY[2] - towerY[0];
return sqrt((fsquare(x1) + fsquare(y1)) * (fsquare(x2) + fsquare(y2)) * (fsquare(y1 - y2) + fsquare(x1 - x2)))/(2 * fabs(x1 * y2 - x2 * y1));
}
}
float DeltaParameters::GetXCorrection() const
{
return (isEquilateral) ? 0.0 : (acos((towerX[Z_AXIS] - towerX[X_AXIS])/GetRadius()) * (180.0/PI)) - 30;
}
float DeltaParameters::GetYCorrection() const
{
return (isEquilateral) ? 0.0 : 30 - (acos((towerX[Y_AXIS] - towerX[Z_AXIS])/GetRadius()) * (180.0/PI));
}
void DeltaParameters::SetRadius(float r)
{
radius = r;
isEquilateral = true;
const float cos30 = sqrtf(3.0)/2.0;
const float sin30 = 0.5;
towerX[A_AXIS] = -(r * cos30);
towerX[B_AXIS] = r * cos30;
towerX[C_AXIS] = 0.0;
towerY[A_AXIS] = towerY[B_AXIS] = -(r * sin30);
towerY[C_AXIS] = r;
Recalc();
}
void DeltaParameters::Recalc()
{
deltaMode = (radius > 0.0 && diagonal > radius);
if (deltaMode)
{
Xbc = towerX[C_AXIS] - towerX[B_AXIS];
Xca = towerX[A_AXIS] - towerX[C_AXIS];
Xab = towerX[B_AXIS] - towerX[A_AXIS];
Ybc = towerY[C_AXIS] - towerY[B_AXIS];
Yca = towerY[A_AXIS] - towerY[C_AXIS];
Yab = towerY[B_AXIS] - towerY[A_AXIS];
coreFa = fsquare(towerX[A_AXIS]) + fsquare(towerY[A_AXIS]);
coreFb = fsquare(towerX[B_AXIS]) + fsquare(towerY[B_AXIS]);
coreFc = fsquare(towerX[C_AXIS]) + fsquare(towerY[C_AXIS]);
Q = 2 * (Xca * Yab - Xab * Yca);
Q2 = fsquare(Q);
D2 = fsquare(diagonal);
// Calculate the base carriage height when the printer is homed.
const float tempHeight = diagonal; // any sensible height will do here, probably even zero
float machinePos[AXES];
InverseTransform(tempHeight + endstopAdjustments[X_AXIS], tempHeight + endstopAdjustments[Y_AXIS], tempHeight + endstopAdjustments[X_AXIS],
machinePos);
homedCarriageHeight = homedHeight + tempHeight - machinePos[Z_AXIS];
}
}
// Make the average of the endstop adjustments zero, without changing the individual homed carriage heights
void DeltaParameters::NormaliseEndstopAdjustments()
{
const float eav = (endstopAdjustments[A_AXIS] + endstopAdjustments[B_AXIS] + endstopAdjustments[C_AXIS])/3.0;
endstopAdjustments[A_AXIS] -= eav;
endstopAdjustments[B_AXIS] -= eav;
endstopAdjustments[C_AXIS] -= eav;
homedHeight += eav;
homedCarriageHeight += eav; // no need for a full recalc, this is sufficient
}
// Calculate the motor position for a single tower from a Cartesian coordinate
float DeltaParameters::Transform(const float machinePos[AXES], size_t axis) const
{
return machinePos[Z_AXIS]
+ sqrt(D2 - fsquare(machinePos[X_AXIS] - towerX[axis]) - fsquare(machinePos[Y_AXIS] - towerY[axis]));
}
void DeltaParameters::InverseTransform(float Ha, float Hb, float Hc, float machinePos[AXES]) const
{
const float Fa = coreFa + fsquare(Ha);
const float Fb = coreFb + fsquare(Hb);
const float Fc = coreFc + fsquare(Hc);
// debugPrintf("Ha=%f Hb=%f Hc=%f Fa=%f Fb=%f Fc=%f Xbc=%f Xca=%f Xab=%f Ybc=%f Yca=%f Yab=%f\n",
// Ha, Hb, Hc, Fa, Fb, Fc, Xbc, Xca, Xab, Ybc, Yca, Yab);
// Setup PQRSU such that x = -(S - uz)/P, y = (P - Rz)/Q
const float P = (Xbc * Fa) + (Xca * Fb) + (Xab * Fc);
const float S = (Ybc * Fa) + (Yca * Fb) + (Yab * Fc);
const float R = 2 * ((Xbc * Ha) + (Xca * Hb) + (Xab * Hc));
const float U = 2 * ((Ybc * Ha) + (Yca * Hb) + (Yab * Hc));
// debugPrintf("P= %f R=%f S=%f U=%f Q=%f\n", P, R, S, U, Q);
const float R2 = fsquare(R), U2 = fsquare(U);
float A = U2 + R2 + Q2;
float minusHalfB = S * U + P * R + Ha * Q2 + towerX[A_AXIS] * U * Q - towerY[A_AXIS] * R * Q;
float C = fsquare(S + towerX[A_AXIS] * Q) + fsquare(P - towerY[A_AXIS] * Q) + (fsquare(Ha) - D2) * Q2;
// debugPrintf("A=%f minusHalfB=%f C=%f\n", A, minusHalfB, C);
float z = (minusHalfB - sqrtf(fsquare(minusHalfB) - A * C)) / A;
machinePos[X_AXIS] = (U * z - S) / Q;
machinePos[Y_AXIS] = (P - R * z) / Q;
machinePos[Z_AXIS] = z;
}
// Compute the derivative of height with respect to a parameter at the specified motor endpoints.
// 'deriv' indicates the parameter as follows:
// 0, 1, 2 = X, Y, Z tower endstop adjustments
// 3, 4 = X, Y tower X position
// 5 = Z tower Y position
// 6 = diagonal rod length
// 7 = delta radius (only if isEquilateral is true)
float DeltaParameters::ComputeDerivative(unsigned int deriv, float ha, float hb, float hc)
{
const float perturb = 0.2; // perturbation amount in mm
DeltaParameters hiParams(*this), loParams(*this);
switch(deriv)
{
case 0:
case 1:
case 2:
break;
case 3:
case 4:
hiParams.towerX[deriv - 3] += perturb;
loParams.towerX[deriv - 3] -= perturb;
break;
case 5:
{
const float yAdj = perturb * (1.0/3.0);
hiParams.towerY[A_AXIS] -= yAdj;
hiParams.towerY[B_AXIS] -= yAdj;
hiParams.towerY[C_AXIS] += (perturb - yAdj);
loParams.towerY[A_AXIS] += yAdj;
loParams.towerY[B_AXIS] += yAdj;
loParams.towerY[C_AXIS] -= (perturb - yAdj);
}
break;
case 6:
hiParams.diagonal += perturb;
loParams.diagonal -= perturb;
break;
case 7:
hiParams.SetRadius(radius + perturb);
loParams.SetRadius(radius - perturb);
break;
}
hiParams.Recalc();
loParams.Recalc();
float newPos[AXES];
hiParams.InverseTransform((deriv == 0) ? ha + perturb : ha, (deriv == 1) ? hb + perturb : hb, (deriv == 2) ? hc + perturb : hc, newPos);
float zHi = newPos[Z_AXIS];
loParams.InverseTransform((deriv == 0) ? ha - perturb : ha, (deriv == 1) ? hb - perturb : hb, (deriv == 2) ? hc - perturb : hc, newPos);
float zLo = newPos[Z_AXIS];
return (zHi - zLo)/(2 * perturb);
}
// Perform 3, 4, 6 or 7-factor adjustment.
// The input vector contains the following parameters in this order:
// X, Y and Z endstop adjustments
// If we are doing 4-factor adjustment, the next argument is the delta radius. Otherwise:
// X tower X position adjustment
// Y tower X position adjustment
// Z tower Y position adjustment
// Diagonal rod length adjustment
void DeltaParameters::Adjust(size_t numFactors, const float v[])
{
const float oldCarriageHeightA = GetHomedCarriageHeight(A_AXIS); // save for later
// Update endstop adjustments
endstopAdjustments[A_AXIS] += v[0];
endstopAdjustments[B_AXIS] += v[1];
endstopAdjustments[C_AXIS] += v[2];
NormaliseEndstopAdjustments();
if (numFactors == 4)
{
// 4-factor adjustment, so update delta radius
SetRadius(radius + v[3]); // this sets isEquilateral true, recalculates tower positions, then calls Recalc()
}
else if (numFactors > 3)
{
// 6- or 7-factor adjustment
towerX[A_AXIS] += v[3];
towerX[B_AXIS] += v[4];
const float yAdj = v[5] * (1.0/3.0);
towerY[A_AXIS] -= yAdj;
towerY[B_AXIS] -= yAdj;
towerY[C_AXIS] += (v[5] - yAdj);
isEquilateral = false;
if (numFactors == 7)
{
diagonal += v[6];
}
Recalc();
}
// Adjusting the diagonal and the tower positions affects the homed carriage height.
// We need to adjust homedHeight to allow for this, to get the change that was requested in the endstop corrections.
const float heightError = GetHomedCarriageHeight(A_AXIS) - oldCarriageHeightA - v[0];
homedHeight -= heightError;
homedCarriageHeight -= heightError;
}
void DeltaParameters::PrintParameters(StringRef& reply) const
{
reply.printf("Endstops X%.2f Y%.2f Z%.2f, height %.2f, diagonal %.2f, radius %.2f",
endstopAdjustments[A_AXIS], endstopAdjustments[B_AXIS], endstopAdjustments[C_AXIS], homedHeight, diagonal, GetRadius());
if (isEquilateral)
{
reply.cat("\n");
}
else
{
reply.catf(", towers (%.2f,%.2f) (%.2f,%.2f) (%.2f,%.2f)\n",
towerX[A_AXIS], towerY[A_AXIS], towerX[B_AXIS], towerY[B_AXIS], towerX[C_AXIS], towerY[C_AXIS]);
}
}
// End