
routine executes in 6.5 microseconds, so we shouldn't have any trouble driving the steppers fast...
257 lines
5.9 KiB
C++
257 lines
5.9 KiB
C++
/****************************************************************************************************
|
|
|
|
RepRapFirmware - Move
|
|
|
|
This is all the code to deal with movement and kinematics.
|
|
|
|
-----------------------------------------------------------------------------------------------------
|
|
|
|
Version 0.1
|
|
|
|
18 November 2012
|
|
|
|
Adrian Bowyer
|
|
RepRap Professional Ltd
|
|
http://reprappro.com
|
|
|
|
Licence: GPL
|
|
|
|
****************************************************************************************************/
|
|
|
|
#include "RepRapFirmware.h"
|
|
|
|
Move::Move(Platform* p, GCodes* g)
|
|
{
|
|
active = false;
|
|
platform = p;
|
|
gCodes = g;
|
|
dda = new DDA(this, platform);
|
|
}
|
|
|
|
void Move::Init()
|
|
{
|
|
char i;
|
|
|
|
for(i = 0; i < DRIVES; i++)
|
|
platform->SetDirection(i, FORWARDS);
|
|
for(i = 0; i <= AXES; i++)
|
|
currentPosition[i] = 0.0;
|
|
lastTime = platform->Time();
|
|
currentFeedrate = START_FEED_RATE;
|
|
float dx = 1.0/platform->DriveStepsPerUnit(X_AXIS);
|
|
float dy = 1.0/platform->DriveStepsPerUnit(Y_AXIS);
|
|
float dz = 1.0/platform->DriveStepsPerUnit(Z_AXIS);
|
|
stepDistances[0] = dx; // Should never be used. Wrong, but safer than 0.0...
|
|
stepDistances[1] = dx;
|
|
stepDistances[2] = dy;
|
|
stepDistances[3] = sqrt(dx*dx + dy*dy);
|
|
stepDistances[4] = dz;
|
|
stepDistances[5] = sqrt(dx*dx + dz*dz);
|
|
stepDistances[6] = sqrt(dy*dy + dz*dz);
|
|
stepDistances[7] = sqrt(dx*dx + dy*dy + dz*dz);
|
|
|
|
active = true;
|
|
}
|
|
|
|
void Move::Exit()
|
|
{
|
|
active = false;
|
|
}
|
|
|
|
void Move::Spin()
|
|
{
|
|
if(!active)
|
|
return;
|
|
Qmove();
|
|
}
|
|
|
|
|
|
void Move::Qmove()
|
|
{
|
|
//char scratchString[STRING_LENGTH];
|
|
if(!gCodes->ReadMove(nextMove))
|
|
return;
|
|
/* platform->Message(HOST_MESSAGE, "Move - got a move:");
|
|
for(char i = 0; i <= DRIVES; i++)
|
|
{
|
|
ftoa(scratchString, nextMove[i], 3);
|
|
platform->Message(HOST_MESSAGE, scratchString);
|
|
platform->Message(HOST_MESSAGE, ", ");
|
|
}
|
|
platform->Message(HOST_MESSAGE, "\n");*/
|
|
|
|
boolean work = dda->Init(currentPosition, nextMove);
|
|
|
|
for(char i = 0; i <= AXES; i++)
|
|
currentPosition[i] = nextMove[i];
|
|
|
|
if(work)
|
|
dda->Start(true);
|
|
}
|
|
|
|
void Move::GetCurrentState(float m[])
|
|
{
|
|
for(char i = 0; i < DRIVES; i++)
|
|
{
|
|
if(i < AXES)
|
|
m[i] = currentPosition[i];
|
|
else
|
|
m[i] = 0.0;
|
|
}
|
|
m[DRIVES] = currentFeedrate;
|
|
}
|
|
|
|
//****************************************************************************************************
|
|
|
|
DDA::DDA(Move* m, Platform* p)
|
|
{
|
|
active = false;
|
|
move = m;
|
|
platform = p;
|
|
}
|
|
|
|
boolean DDA::Init(float currentPosition[], float targetPosition[])
|
|
{
|
|
char drive;
|
|
active = false;
|
|
totalSteps = -1;
|
|
float dist = 0; // X+Y+Z
|
|
float d;
|
|
char axesMoving = 0;
|
|
for(drive = 0; drive < DRIVES; drive++)
|
|
{
|
|
if(drive < AXES)
|
|
{
|
|
d = targetPosition[drive] - currentPosition[drive];
|
|
delta[drive] = (long)(d*platform->DriveStepsPerUnit(drive)); //Absolute
|
|
dist += d*d;
|
|
} else
|
|
delta[drive] = (long)(targetPosition[drive]*platform->DriveStepsPerUnit(drive)); // Relative
|
|
if(delta[drive] >= 0)
|
|
directions[drive] = FORWARDS;
|
|
else
|
|
directions[drive] = BACKWARDS;
|
|
delta[drive] = abs(delta[drive]);
|
|
if(drive == X_AXIS && delta[drive] > 0)
|
|
axesMoving |= 1;
|
|
if(drive == Y_AXIS && delta[drive] > 0)
|
|
axesMoving |= 2;
|
|
if(drive == Z_AXIS && delta[drive] > 0)
|
|
axesMoving |= 4;
|
|
if(delta[drive] > totalSteps)
|
|
totalSteps = delta[drive];
|
|
}
|
|
if(totalSteps <= 0)
|
|
return false;
|
|
counter[0] = totalSteps/2;
|
|
for(drive = 1; drive < DRIVES; drive++)
|
|
counter[drive] = counter[0];
|
|
dist = sqrt(dist);
|
|
float acc;
|
|
if(axesMoving|4)
|
|
{
|
|
acc = platform->Acceleration(Z_AXIS);
|
|
velocity = platform->Jerk(Z_AXIS);
|
|
} else
|
|
{
|
|
acc = platform->Acceleration(X_AXIS);
|
|
velocity = platform->Jerk(X_AXIS);
|
|
}
|
|
|
|
timeStep = move->stepDistances[1]/velocity;
|
|
d = 0.5*(targetPosition[DRIVES]*targetPosition[DRIVES] - velocity*velocity)/acc; // d = (v^2 - u^2)/2a
|
|
stopAStep = (long)((d*totalSteps)/dist);
|
|
startDStep = totalSteps - stopAStep;
|
|
if(stopAStep > startDStep)
|
|
{
|
|
stopAStep = totalSteps/2;
|
|
startDStep = stopAStep + 1;
|
|
}
|
|
stepCount = 0;
|
|
return true;
|
|
}
|
|
|
|
void DDA::Start(boolean noTest)
|
|
{
|
|
for(char drive = 0; drive < DRIVES; drive++)
|
|
platform->SetDirection(drive, directions[drive]);
|
|
if(noTest)
|
|
platform->SetInterrupt((long)(1.0e6*timeStep));
|
|
active = true;
|
|
}
|
|
|
|
void DDA::Step(boolean noTest)
|
|
{
|
|
if(!active && noTest)
|
|
return;
|
|
|
|
char axesMoving = 0;
|
|
|
|
counter[X_AXIS] += delta[X_AXIS];
|
|
if(counter[X_AXIS] > 0)
|
|
{
|
|
if(noTest)
|
|
platform->Step(X_AXIS);
|
|
axesMoving |= 1;
|
|
counter[X_AXIS] -= totalSteps;
|
|
}
|
|
|
|
counter[Y_AXIS] += delta[Y_AXIS];
|
|
if(counter[Y_AXIS] > 0)
|
|
{
|
|
if(noTest)
|
|
platform->Step(Y_AXIS);
|
|
axesMoving |= 2;
|
|
counter[Y_AXIS] -= totalSteps;
|
|
}
|
|
|
|
counter[Z_AXIS] += delta[Z_AXIS];
|
|
if(counter[Z_AXIS] > 0)
|
|
{
|
|
if(noTest)
|
|
platform->Step(Z_AXIS);
|
|
axesMoving |= 4;
|
|
counter[Z_AXIS] -= totalSteps;
|
|
}
|
|
|
|
|
|
for(char drive = AXES; drive < DRIVES; drive++)
|
|
{
|
|
counter[drive] += delta[drive];
|
|
if(counter[drive] > 0)
|
|
{
|
|
if(noTest)
|
|
platform->Step(drive);
|
|
counter[drive] -= totalSteps;
|
|
}
|
|
}
|
|
|
|
if(axesMoving)
|
|
{
|
|
if(stepCount < stopAStep)
|
|
{
|
|
timeStep = move->stepDistances[axesMoving]/velocity;
|
|
if(axesMoving & 4)
|
|
velocity += platform->Acceleration(Z_AXIS)*timeStep;
|
|
else
|
|
velocity += platform->Acceleration(X_AXIS)*timeStep;
|
|
if(noTest)
|
|
platform->SetInterrupt((long)(1.0e6*timeStep));
|
|
}
|
|
if(stepCount >= startDStep)
|
|
{
|
|
timeStep = move->stepDistances[axesMoving]/velocity;
|
|
if(axesMoving & 4)
|
|
velocity -= platform->Acceleration(Z_AXIS)*timeStep;
|
|
else
|
|
velocity -= platform->Acceleration(X_AXIS)*timeStep;
|
|
if(noTest)
|
|
platform->SetInterrupt((long)(1.0e6*timeStep));
|
|
}
|
|
}
|
|
|
|
stepCount++;
|
|
active = stepCount < totalSteps;
|
|
if(!active && noTest)
|
|
platform->SetInterrupt(-1);
|
|
}
|