This version is broken. But it is better! Major rewrite of the Move class. Now to debug it...
This commit is contained in:
parent
a5c2b5b80e
commit
1e35269a06
12 changed files with 535 additions and 216 deletions
|
@ -32,36 +32,9 @@ Licence: GPL
|
|||
|
||||
#define INCH_TO_MM 25.4
|
||||
|
||||
#define FLASH_LED 'F' // Type byte of a message that is to flash an LED; the next two bytes define
|
||||
// the frequency and M/S ratio.
|
||||
#define DISPLAY_MESSAGE 'L' // Type byte of a message that is to appear on a local display; the L is
|
||||
// not displayed; \f and \n should be supported.
|
||||
#define HOST_MESSAGE 'H' // Type byte of a message that is to be sent to the host; the H is not sent.
|
||||
|
||||
|
||||
// Webserver stuff
|
||||
|
||||
#define DEFAULT_PASSWORD "reprap"
|
||||
|
||||
#define DEFAULT_NAME "My RepRap 1"
|
||||
|
||||
#define CLIENT_CLOSE_DELAY 1000 // Microseconds to wait after serving a page
|
||||
|
||||
#define INDEX_PAGE "reprap.htm"
|
||||
#define MESSAGE_FILE "messages.txt"
|
||||
#define FOUR04_FILE "html404.htm"
|
||||
#define KO_START "rr_"
|
||||
#define KO_FIRST 3
|
||||
#define STRING_LENGTH 1000
|
||||
#define POST_LENGTH 200
|
||||
#define START_FEED_RATE 200.0
|
||||
#define GCODE_LENGTH 100 // Maximum lenght of internally-generated G Code string
|
||||
|
||||
// Movement stuff
|
||||
|
||||
#define RING_LENGTH 10
|
||||
|
||||
#define LOOK_AHEAD_LENGTH 25
|
||||
#define LOOK_AHEAD_FLUSH 5
|
||||
#define LOOK_AHEAD_FUTURE 15
|
||||
#endif
|
||||
|
|
9
GCodes.h
9
GCodes.h
|
@ -22,6 +22,7 @@ Licence: GPL
|
|||
#ifndef GCODES_H
|
||||
#define GCODES_H
|
||||
|
||||
|
||||
// Small class to hold an individual GCode
|
||||
|
||||
class GCodeBuffer
|
||||
|
@ -40,7 +41,8 @@ class GCodeBuffer
|
|||
Platform* platform;
|
||||
char gcodeBuffer[GCODE_LENGTH];
|
||||
int gcodePointer;
|
||||
int readPointer;
|
||||
int readPointer;
|
||||
boolean inComment;
|
||||
};
|
||||
|
||||
//****************************************************************************************************
|
||||
|
@ -55,7 +57,7 @@ class GCodes
|
|||
void Spin();
|
||||
void Init();
|
||||
void Exit();
|
||||
boolean ReadMove(float* m);
|
||||
boolean ReadMove(float* m, boolean& ce);
|
||||
boolean ReadHeat(float* h);
|
||||
void QueueFileToPrint(char* fileName);
|
||||
boolean PrintingAFile();
|
||||
|
@ -65,6 +67,7 @@ class GCodes
|
|||
boolean ActOnGcode(GCodeBuffer* gb);
|
||||
boolean SetUpMove(GCodeBuffer* gb);
|
||||
boolean DoDwell(GCodeBuffer *gb);
|
||||
boolean DoHome();
|
||||
Platform* platform;
|
||||
boolean active;
|
||||
Webserver* webserver;
|
||||
|
@ -77,6 +80,7 @@ class GCodes
|
|||
boolean moveAvailable;
|
||||
boolean heatAvailable;
|
||||
float moveBuffer[DRIVES+1]; // Last is feedrate
|
||||
boolean checkEndStops;
|
||||
boolean drivesRelative; // All except X, Y and Z
|
||||
boolean axesRelative; // X, Y and Z
|
||||
char gCodeLetters[DRIVES + 1]; // Extra is for F
|
||||
|
@ -84,6 +88,7 @@ class GCodes
|
|||
float distanceScale;
|
||||
int fileBeingPrinted;
|
||||
int fileToPrint;
|
||||
char homeToDo;
|
||||
};
|
||||
|
||||
//*****************************************************************************************************
|
||||
|
|
71
GCodes.ino
71
GCodes.ino
|
@ -46,12 +46,14 @@ void GCodes::Init()
|
|||
heatAvailable = false;
|
||||
drivesRelative = true;
|
||||
axesRelative = false;
|
||||
checkEndStops = false;
|
||||
gCodeLetters = GCODE_LETTERS;
|
||||
distanceScale = 1.0;
|
||||
for(char i = 0; i < DRIVES - AXES; i++)
|
||||
lastPos[i] = 0.0;
|
||||
fileBeingPrinted = -1;
|
||||
fileToPrint = -1;
|
||||
homeToDo = 0;
|
||||
dwellWaiting = false;
|
||||
dwellTime = platform->Time();
|
||||
}
|
||||
|
@ -154,6 +156,42 @@ boolean GCodes::SetUpMove(GCodeBuffer *gb)
|
|||
return true;
|
||||
}
|
||||
|
||||
boolean GCodes::DoHome()
|
||||
{
|
||||
// Treat more or less like any other move
|
||||
|
||||
// Last one gone yet?
|
||||
|
||||
if(moveAvailable)
|
||||
return false;
|
||||
|
||||
// Wait for all the queued moves to stop
|
||||
|
||||
if(!reprap.GetMove()->AllMovesAreFinished())
|
||||
return false;
|
||||
reprap.GetMove()->ResumeMoving();
|
||||
|
||||
// Load the last position; If Move can't accept more, return false
|
||||
|
||||
if(!reprap.GetMove()->GetCurrentState(moveBuffer))
|
||||
return false;
|
||||
|
||||
for(char i = 0; i < AXES; i++)
|
||||
{
|
||||
if(homeToDo & 1<<i)
|
||||
{
|
||||
moveBuffer[i] = -2.0*platform->AxisLength(i);
|
||||
moveBuffer[DRIVES] = platform->HomeFeedRate(i)/60.0;
|
||||
homeToDo &= ~(1<<i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
moveAvailable = true;
|
||||
|
||||
return homeToDo == 0;
|
||||
}
|
||||
|
||||
void GCodes::QueueFileToPrint(char* fileName)
|
||||
{
|
||||
fileToPrint = platform->OpenFile(platform->GetGCodeDir(), fileName, false);
|
||||
|
@ -233,7 +271,17 @@ boolean GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
break;
|
||||
|
||||
case 28: // Home
|
||||
platform->Message(HOST_MESSAGE, "Home received\n");
|
||||
if(homeToDo == 0)
|
||||
{
|
||||
for(char i = 0; i < AXES; i++)
|
||||
{
|
||||
if(gb->Seen(gCodeLetters[i]))
|
||||
homeToDo |= 1<<i;
|
||||
}
|
||||
if(homeToDo == 0)
|
||||
homeToDo = 7;
|
||||
}
|
||||
result = DoHome();
|
||||
break;
|
||||
|
||||
case 90: // Absolute coordinates
|
||||
|
@ -353,12 +401,13 @@ boolean GCodes::ActOnGcode(GCodeBuffer *gb)
|
|||
|
||||
|
||||
|
||||
boolean GCodes::ReadMove(float* m)
|
||||
boolean GCodes::ReadMove(float* m, boolean& ce)
|
||||
{
|
||||
if(!moveAvailable)
|
||||
return false;
|
||||
for(char i = 0; i <= DRIVES; i++) // 1 more for F
|
||||
m[i] = moveBuffer[i];
|
||||
ce = checkEndStops;
|
||||
moveAvailable = false;
|
||||
}
|
||||
|
||||
|
@ -377,8 +426,9 @@ GCodeBuffer::GCodeBuffer(Platform* p)
|
|||
|
||||
void GCodeBuffer::Init()
|
||||
{
|
||||
gcodePointer = 0;
|
||||
readPointer = -1;
|
||||
gcodePointer = 0;
|
||||
readPointer = -1;
|
||||
inComment = false;
|
||||
}
|
||||
|
||||
boolean GCodeBuffer::Put(char c)
|
||||
|
@ -386,13 +436,20 @@ boolean GCodeBuffer::Put(char c)
|
|||
boolean result = false;
|
||||
|
||||
gcodeBuffer[gcodePointer] = c;
|
||||
if(gcodeBuffer[gcodePointer] == '\n' || !gcodeBuffer[gcodePointer])
|
||||
|
||||
if(c == ';')
|
||||
inComment = true;
|
||||
|
||||
if(c == '\n' || !c)
|
||||
{
|
||||
gcodeBuffer[gcodePointer] = 0;
|
||||
gcodePointer = 0;
|
||||
Init();
|
||||
result = true;
|
||||
} else
|
||||
gcodePointer++;
|
||||
{
|
||||
if(!inComment)
|
||||
gcodePointer++;
|
||||
}
|
||||
|
||||
if(gcodePointer >= GCODE_LENGTH)
|
||||
{
|
||||
|
|
173
Move.h
173
Move.h
|
@ -21,12 +21,63 @@ Licence: GPL
|
|||
#ifndef MOVE_H
|
||||
#define MOVE_H
|
||||
|
||||
#define DDA_RING_LENGTH 5
|
||||
#define LOOK_AHEAD_RING_LENGTH 20
|
||||
#define LOOK_AHEAD 7
|
||||
|
||||
enum MovementProfile
|
||||
{
|
||||
nothing = 0, // No movement (i.e. end-position == start).
|
||||
moving = 1, // Ordinary trapezoidal-velocity-profile movement
|
||||
noFlat = 2, // Triangular profile movement
|
||||
change = 3 // To make this movement, the initial and final velocities must change
|
||||
moving = 0, // Ordinary trapezoidal-velocity-profile movement
|
||||
noFlat = 1, // Triangular profile movement
|
||||
change = 2 // To make this movement, the initial and final velocities must change
|
||||
};
|
||||
|
||||
enum MovementState
|
||||
{
|
||||
unprocessed = 0,
|
||||
vCosineSet = 1,
|
||||
upPass = 2,
|
||||
complete = 4,
|
||||
released = 8
|
||||
};
|
||||
|
||||
enum MovementType
|
||||
{
|
||||
noMove = 0,
|
||||
xyMove = 1,
|
||||
zMove = 2,
|
||||
eMove = 4
|
||||
};
|
||||
|
||||
class LookAhead
|
||||
{
|
||||
public:
|
||||
LookAhead(Move* m, Platform* p, LookAhead* n);
|
||||
LookAhead* Next();
|
||||
LookAhead* Previous();
|
||||
void Init(float ep[], float vv, boolean ce);
|
||||
float* EndPoint();
|
||||
float V();
|
||||
void SetV(float vv);
|
||||
char Processed();
|
||||
void SetProcessed(MovementState ms);
|
||||
boolean CheckEndStops();
|
||||
void Release();
|
||||
|
||||
friend class Move;
|
||||
|
||||
private:
|
||||
Move* move;
|
||||
Platform* platform;
|
||||
LookAhead* next;
|
||||
LookAhead* previous;
|
||||
float endPoint[DRIVES+1];
|
||||
float Cosine();
|
||||
boolean checkEndStops;
|
||||
float cosine;
|
||||
float endPosition[DRIVES+1]; // Last is feedrate
|
||||
float v;
|
||||
char processed;
|
||||
};
|
||||
|
||||
|
||||
|
@ -34,7 +85,7 @@ class DDA
|
|||
{
|
||||
public:
|
||||
DDA(Move* m, Platform* p, DDA* n);
|
||||
MovementProfile Init(float currentPosition[], float targetPosition[], float& u, float& v);
|
||||
MovementProfile Init(LookAhead* lookAhead, float& u, float& v);
|
||||
void Start(boolean noTest);
|
||||
void Step(boolean noTest);
|
||||
boolean Active();
|
||||
|
@ -46,11 +97,12 @@ class DDA
|
|||
Move* move;
|
||||
Platform* platform;
|
||||
DDA* next;
|
||||
long counter[DRIVES+1];
|
||||
long delta[DRIVES+1];
|
||||
boolean directions[DRIVES+1];
|
||||
long counter[DRIVES];
|
||||
long delta[DRIVES];
|
||||
boolean directions[DRIVES];
|
||||
long totalSteps;
|
||||
long stepCount;
|
||||
boolean checkEndStops;
|
||||
float timeStep;
|
||||
float velocity;
|
||||
long stopAStep;
|
||||
|
@ -58,36 +110,11 @@ class DDA
|
|||
float distance;
|
||||
float dCross;
|
||||
float acceleration;
|
||||
float jerk;
|
||||
float instantDv;
|
||||
volatile boolean active;
|
||||
};
|
||||
|
||||
class LookAhead
|
||||
{
|
||||
public:
|
||||
LookAhead(Move* m, Platform* p, LookAhead* n);
|
||||
LookAhead* Next();
|
||||
LookAhead* Previous();
|
||||
void Init(float m[], float uu, float vv);
|
||||
void SetUV(float uu, float vv);
|
||||
float* Movement();
|
||||
float U();
|
||||
float V();
|
||||
boolean Processed();
|
||||
void SetProcessed();
|
||||
|
||||
friend class Move;
|
||||
|
||||
private:
|
||||
Move* move;
|
||||
Platform* platform;
|
||||
LookAhead* next;
|
||||
LookAhead* previous;
|
||||
float Cosine(LookAhead* a);
|
||||
float movement[DRIVES+1]; // Last is feedrate
|
||||
float u, v;
|
||||
boolean processed;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Move
|
||||
|
@ -103,12 +130,15 @@ class Move
|
|||
void InterruptTime();
|
||||
boolean AllMovesAreFinished();
|
||||
void ResumeMoving();
|
||||
void DoLookAhead();
|
||||
void HitLowStop(char drive);
|
||||
void HitHighStop(char drive);
|
||||
|
||||
friend class DDA;
|
||||
|
||||
private:
|
||||
|
||||
boolean DDARingAdd(float currentPosition[], float targetPosition[], float& u, float& v);
|
||||
boolean DDARingAdd(LookAhead* lookAhead);
|
||||
DDA* DDARingGet();
|
||||
boolean DDARingEmpty();
|
||||
boolean DDARingFull();
|
||||
|
@ -116,8 +146,10 @@ class Move
|
|||
void ReleaseDDARingLock();
|
||||
boolean LookAheadRingEmpty();
|
||||
boolean LookAheadRingFull();
|
||||
boolean LookAheadRingAdd(float m[], float uu, float vv);
|
||||
boolean LookAheadRingAdd(float ep[], float vv, boolean ce);
|
||||
LookAhead* LookAheadRingGet();
|
||||
char GetMovementType(float sp[], float ep[]);
|
||||
|
||||
|
||||
Platform* platform;
|
||||
GCodes* gCodes;
|
||||
|
@ -137,6 +169,7 @@ class Move
|
|||
boolean addNoMoreMoves;
|
||||
boolean active;
|
||||
boolean moveWaiting;
|
||||
boolean checkEndStopsOnNextMove;
|
||||
float currentFeedrate;
|
||||
float currentPosition[AXES]; // Note - drives above AXES are always relative moves
|
||||
float nextMove[DRIVES + 1]; // Extra is for feedrate
|
||||
|
@ -146,16 +179,6 @@ class Move
|
|||
|
||||
//********************************************************************************************************
|
||||
|
||||
inline boolean DDA::Active()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
inline DDA* DDA::Next()
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
inline LookAhead* LookAhead::Next()
|
||||
{
|
||||
return next;
|
||||
|
@ -166,37 +189,61 @@ inline LookAhead* LookAhead::Previous()
|
|||
return previous;
|
||||
}
|
||||
|
||||
inline void LookAhead::SetUV(float uu, float vv)
|
||||
|
||||
inline void LookAhead::SetV(float vv)
|
||||
{
|
||||
u = uu;
|
||||
v = vv;
|
||||
}
|
||||
|
||||
inline float* LookAhead::Movement()
|
||||
inline float* LookAhead::EndPoint()
|
||||
{
|
||||
return movement;
|
||||
return endPoint;
|
||||
}
|
||||
|
||||
inline float LookAhead::U()
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
inline float LookAhead::V()
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
inline boolean LookAhead::Processed()
|
||||
inline char LookAhead::Processed()
|
||||
{
|
||||
return processed;
|
||||
}
|
||||
|
||||
inline void LookAhead::SetProcessed()
|
||||
inline void LookAhead::SetProcessed(MovementState ms)
|
||||
{
|
||||
processed = true;
|
||||
if(ms == 0)
|
||||
processed = 0;
|
||||
else
|
||||
processed |= ms;
|
||||
}
|
||||
|
||||
inline void LookAhead::Release()
|
||||
{
|
||||
processed = released;
|
||||
}
|
||||
|
||||
inline boolean LookAhead::CheckEndStops()
|
||||
{
|
||||
return checkEndStops;
|
||||
}
|
||||
|
||||
//******************************************************************************************************
|
||||
|
||||
inline boolean DDA::Active()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
inline DDA* DDA::Next()
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************
|
||||
|
||||
inline boolean Move::DDARingEmpty()
|
||||
{
|
||||
return ddaRingGetPointer == ddaRingAddPointer;
|
||||
|
@ -251,5 +298,15 @@ inline void Move::ResumeMoving()
|
|||
addNoMoreMoves = false;
|
||||
}
|
||||
|
||||
inline void Move::HitLowStop(char drive)
|
||||
{
|
||||
// Put some code here
|
||||
}
|
||||
|
||||
inline void Move::HitHighStop(char drive)
|
||||
{
|
||||
// and here
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
351
Move.ino
351
Move.ino
|
@ -31,23 +31,26 @@ Move::Move(Platform* p, GCodes* g)
|
|||
|
||||
ddaRingAddPointer = new DDA(this, platform, NULL);
|
||||
dda = ddaRingAddPointer;
|
||||
for(i = 1; i < RING_LENGTH; i++)
|
||||
for(i = 1; i < DDA_RING_LENGTH; i++)
|
||||
dda = new DDA(this, platform, dda);
|
||||
ddaRingAddPointer->next = dda;
|
||||
|
||||
dda = NULL;
|
||||
|
||||
// Build the lookahead ring
|
||||
|
||||
lookAheadRingAddPointer = new LookAhead(this, platform, NULL);
|
||||
lookAheadRingGetPointer = lookAheadRingAddPointer;
|
||||
for(i = 1; i < RING_LENGTH; i++)
|
||||
for(i = 1; i < LOOK_AHEAD_RING_LENGTH; i++)
|
||||
lookAheadRingGetPointer = new LookAhead(this, platform, lookAheadRingGetPointer);
|
||||
lookAheadRingAddPointer->next = lookAheadRingGetPointer;
|
||||
|
||||
// Set the backwards pointers
|
||||
// Set the backwards pointers and flag them all as free
|
||||
|
||||
lookAheadRingGetPointer = lookAheadRingAddPointer;
|
||||
for(i = 0; i <= RING_LENGTH; i++)
|
||||
for(i = 0; i <= LOOK_AHEAD_RING_LENGTH; i++)
|
||||
{
|
||||
lookAheadRingAddPointer->SetProcessed(released);
|
||||
lookAheadRingAddPointer = lookAheadRingAddPointer->Next();
|
||||
lookAheadRingAddPointer->previous = lookAheadRingGetPointer;
|
||||
lookAheadRingGetPointer = lookAheadRingAddPointer;
|
||||
|
@ -83,13 +86,14 @@ void Move::Init()
|
|||
for(i = 0; i < DRIVES; i++)
|
||||
nextMove[i] = 0.0;
|
||||
nextMove[DRIVES] = currentFeedrate;
|
||||
LookAheadRingAdd(nextMove, 0.0, 0.0);
|
||||
checkEndStopsOnNextMove = false;
|
||||
LookAheadRingAdd(nextMove, 0.0, false);
|
||||
|
||||
// Now remove it from the ring; it will remain as what is now the
|
||||
// previous move, so the first real move will see that as
|
||||
// the place to move from.
|
||||
// the place to move from. Flag it as fully processed.
|
||||
|
||||
LookAheadRingGet();
|
||||
LookAheadRingGet()->SetProcessed(released);
|
||||
|
||||
// The stepDistances arrays are look-up tables of the Euclidean distance
|
||||
// between the start and end of a step. If the step is just along one axis,
|
||||
|
@ -149,15 +153,15 @@ void Move::Spin()
|
|||
if(!active)
|
||||
return;
|
||||
|
||||
DoLookAhead();
|
||||
|
||||
//FIXME
|
||||
float u = 0.0; // This will provoke the code to select the jerk values.
|
||||
float u = 0.0; // This will provoke the code to select the instantDv values.
|
||||
float v = 0.0;
|
||||
|
||||
if(larWaiting != NULL)
|
||||
{
|
||||
u = larWaiting->U();
|
||||
v = larWaiting->V();
|
||||
if(DDARingAdd(larWaiting->Previous()->Movement(), larWaiting->Movement(), u, v))
|
||||
if(DDARingAdd(larWaiting))
|
||||
larWaiting = NULL;
|
||||
} else
|
||||
{
|
||||
|
@ -169,7 +173,7 @@ void Move::Spin()
|
|||
{
|
||||
if(!addNoMoreMoves)
|
||||
{
|
||||
if(LookAheadRingAdd(nextMove, u, v))
|
||||
if(LookAheadRingAdd(nextMove, v, checkEndStopsOnNextMove))
|
||||
{
|
||||
for(char i = 0; i < AXES; i++)
|
||||
currentPosition[i] = nextMove[i];
|
||||
|
@ -179,13 +183,21 @@ void Move::Spin()
|
|||
}
|
||||
} else
|
||||
{
|
||||
moveWaiting = gCodes->ReadMove(nextMove);
|
||||
moveWaiting = gCodes->ReadMove(nextMove, checkEndStopsOnNextMove);
|
||||
if(moveWaiting)
|
||||
{
|
||||
if(GetMovementType(currentPosition, nextMove) == noMove)
|
||||
{
|
||||
currentFeedrate = nextMove[DRIVES]; // Might be G1 with just an F field
|
||||
moveWaiting = false; // Throw it away
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean Move::GetCurrentState(float m[])
|
||||
{
|
||||
if(DDARingFull())
|
||||
if(LookAheadRingFull())
|
||||
return false;
|
||||
|
||||
for(char i = 0; i < DRIVES; i++)
|
||||
|
@ -199,8 +211,31 @@ boolean Move::GetCurrentState(float m[])
|
|||
return true;
|
||||
}
|
||||
|
||||
char Move::GetMovementType(float p0[], float p1[])
|
||||
{
|
||||
char result = noMove;
|
||||
for(char drive = 0; drive < DRIVES; drive++)
|
||||
{
|
||||
if(drive < AXES)
|
||||
{
|
||||
if( (long)roundf((p1[drive] - p0[drive])*platform->DriveStepsPerUnit(drive)) )
|
||||
{
|
||||
if(drive == Z_AXIS)
|
||||
result |= zMove;
|
||||
else
|
||||
result |= xyMove;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if( (long)roundf(p1[drive]*platform->DriveStepsPerUnit(drive)) )
|
||||
result |= eMove;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean Move::DDARingAdd(float currentPosition[], float targetPosition[], float& u, float& v)
|
||||
|
||||
boolean Move::DDARingAdd(LookAhead* lookAhead)
|
||||
{
|
||||
if(GetDDARingLock())
|
||||
{
|
||||
|
@ -211,16 +246,16 @@ boolean Move::DDARingAdd(float currentPosition[], float targetPosition[], float&
|
|||
}
|
||||
if(ddaRingAddPointer->Active())
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Attempt to alter an active ring buffer entry!\n");
|
||||
platform->Message(HOST_MESSAGE, "Attempt to alter an active ring buffer entry!\n"); // Should never happen...
|
||||
ReleaseDDARingLock();
|
||||
return false;
|
||||
}
|
||||
if(ddaRingAddPointer->Init(currentPosition, targetPosition, u, v) == nothing)
|
||||
{
|
||||
// Throw it away
|
||||
ReleaseDDARingLock();
|
||||
return true;
|
||||
}
|
||||
|
||||
// We don't care about Init()'s return value - that should all have been sorted
|
||||
// out by LookAhead.
|
||||
|
||||
float u, v;
|
||||
ddaRingAddPointer->Init(lookAhead, u, v);
|
||||
ddaRingAddPointer = ddaRingAddPointer->Next();
|
||||
ReleaseDDARingLock();
|
||||
return true;
|
||||
|
@ -248,6 +283,74 @@ DDA* Move::DDARingGet()
|
|||
}
|
||||
|
||||
|
||||
void Move::DoLookAhead()
|
||||
{
|
||||
if(LookAheadRingEmpty())
|
||||
return;
|
||||
|
||||
LookAhead* n0;
|
||||
LookAhead* n1;
|
||||
LookAhead* n2;
|
||||
|
||||
float u, v;
|
||||
|
||||
// if(addNoMoreMoves || !gCodes->PrintingAFile() || lookAheadRingCount >= LOOK_AHEAD)
|
||||
// {
|
||||
/* n2 = lookAheadRingAddPointer->Previous();
|
||||
n1 = n2->Previous();
|
||||
n0 = n1->Previous();
|
||||
while(n1 != lookAheadRingGetPointer)
|
||||
{
|
||||
if(n1->Processed() & vCosineSet)
|
||||
{
|
||||
u = n0->V();
|
||||
v = n1->V();
|
||||
if(lookAheadDDA->Init(n0->EndPosition(), n1->EndPosition(), u, v) & change)
|
||||
{
|
||||
n0->SetV(u);
|
||||
n1->SetV(v);
|
||||
}
|
||||
}
|
||||
n2 = n1;
|
||||
n1 = n0;
|
||||
n0 = n0->Previous();
|
||||
}
|
||||
}*/
|
||||
|
||||
n1 = lookAheadRingGetPointer;
|
||||
n0 = n1->Previous();
|
||||
n2 = n1->Next();
|
||||
while(n2 != lookAheadRingAddPointer)
|
||||
{
|
||||
if(n1->Processed() == unprocessed)
|
||||
{
|
||||
float c = n1->Cosine();
|
||||
c = n1->EndPoint()[DRIVES]*c;
|
||||
if(c <= 0)
|
||||
{
|
||||
char mt = GetMovementType(n0->EndPoint(), n1->EndPoint());
|
||||
if(mt & zMove)
|
||||
c = platform->InstantDv(Z_AXIS);
|
||||
else if (mt & xyMove)
|
||||
c = platform->InstantDv(X_AXIS);
|
||||
else
|
||||
c = platform->InstantDv(AXES); // value for first extruder - slight hack
|
||||
}
|
||||
Serial.print("End V: ");
|
||||
Serial.println(c);
|
||||
n1->SetV(c);
|
||||
//n1->SetProcessed(vCosineSet);
|
||||
n1->SetProcessed(complete);
|
||||
}
|
||||
n0 = n1;
|
||||
n1 = n2;
|
||||
n2 = n2->Next();
|
||||
}
|
||||
n1->SetProcessed(complete);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
void Move::Interrupt()
|
||||
{
|
||||
// Have we got a live DDA?
|
||||
|
@ -273,18 +376,16 @@ void Move::Interrupt()
|
|||
}
|
||||
|
||||
// Yes - it's finished. Throw it away so the code above will then find a new one.
|
||||
// (N.B. This is not a memory leak. The DDAs are stored in the ring buffer, initialised
|
||||
// on boot, and never renewed or overwritten. dda is just a copied pointer.)
|
||||
|
||||
dda = NULL;
|
||||
}
|
||||
|
||||
|
||||
boolean Move::LookAheadRingAdd(float m[], float uu, float vv)
|
||||
boolean Move::LookAheadRingAdd(float ep[], float vv, boolean ce)
|
||||
{
|
||||
if(LookAheadRingFull())
|
||||
return false;
|
||||
lookAheadRingAddPointer->Init(m, uu, vv);
|
||||
lookAheadRingAddPointer->Init(ep, vv, ce);
|
||||
lookAheadRingAddPointer = lookAheadRingAddPointer->Next();
|
||||
lookAheadRingCount++;
|
||||
return true;
|
||||
|
@ -297,7 +398,7 @@ LookAhead* Move::LookAheadRingGet()
|
|||
if(LookAheadRingEmpty())
|
||||
return NULL;
|
||||
result = lookAheadRingGetPointer;
|
||||
if(!result->Processed())
|
||||
if(!(result->Processed() & released))
|
||||
return NULL;
|
||||
lookAheadRingGetPointer = lookAheadRingGetPointer->Next();
|
||||
lookAheadRingCount--;
|
||||
|
@ -305,13 +406,14 @@ LookAhead* Move::LookAheadRingGet()
|
|||
}
|
||||
|
||||
|
||||
// FIXME
|
||||
// This function is never normally called. It is a test to time
|
||||
// the interrupt function. To activate it, uncomment the line that calls
|
||||
// this in Platform.ino.
|
||||
|
||||
void Move::InterruptTime()
|
||||
{
|
||||
char buffer[50];
|
||||
/* char buffer[50];
|
||||
float a[] = {1.0, 2.0, 3.0, 4.0, 5.0};
|
||||
float b[] = {2.0, 3.0, 4.0, 5.0, 6.0};
|
||||
float u = 50;
|
||||
|
@ -325,7 +427,7 @@ void Move::InterruptTime()
|
|||
platform->Message(HOST_MESSAGE, "Time for 100000 calls of the interrupt function: ");
|
||||
sprintf(buffer, "%ld", t);
|
||||
platform->Message(HOST_MESSAGE, buffer);
|
||||
platform->Message(HOST_MESSAGE, " microseconds.\n");
|
||||
platform->Message(HOST_MESSAGE, " microseconds.\n");*/
|
||||
}
|
||||
|
||||
//****************************************************************************************************
|
||||
|
@ -352,11 +454,12 @@ u and v cannot be satisfied with the distance available and reduces them
|
|||
proportionately to give values that can just be achieved, which is why they
|
||||
are passed by reference.
|
||||
|
||||
The return value is true for an actual move, false for a zero-length (i.e. null) move.
|
||||
The return value is indicates if the move is a trapezium or triangle, and if
|
||||
the u and u values need to be changed.
|
||||
|
||||
Every drive has an acceleration associated with it, so when more than one drive is
|
||||
moving there have to be rules of precedence that say which acceleration (and which
|
||||
jerk value) to use.
|
||||
instantDv value) to use.
|
||||
|
||||
The rules are these:
|
||||
|
||||
|
@ -368,7 +471,7 @@ The rules are these:
|
|||
Use the acceleration for the extruder that's moving.
|
||||
|
||||
In the case of multiple extruders moving at once, their minimum acceleration (and its
|
||||
associated jerk) are used. The variables axesMoving and extrudersMoving track what's
|
||||
associated instantDv) are used. The variables axesMoving and extrudersMoving track what's
|
||||
going on. The bits in the char axesMoving are ORed:
|
||||
|
||||
msb -> 00000ZYX <- lsb
|
||||
|
@ -386,17 +489,20 @@ TODO: Worry about having more than eight extruders...
|
|||
|
||||
*/
|
||||
|
||||
MovementProfile DDA::Init(float currentPosition[], float targetPosition[], float& u, float& v)
|
||||
MovementProfile DDA::Init(LookAhead* lookAhead, float& u, float& v)
|
||||
{
|
||||
char drive;
|
||||
active = false;
|
||||
MovementProfile result = nothing;
|
||||
MovementProfile result = moving;
|
||||
totalSteps = -1;
|
||||
distance = 0.0; // X+Y+Z
|
||||
float eDistance = 0.0;
|
||||
float d;
|
||||
unsigned char axesMoving = 0;
|
||||
unsigned char extrudersMoving = 0;
|
||||
float* targetPosition = lookAhead->EndPoint();
|
||||
v = lookAhead->V();
|
||||
float* currentPosition = lookAhead->Previous()->EndPoint();
|
||||
u = lookAhead->Previous()->V();
|
||||
checkEndStops = lookAhead->CheckEndStops();
|
||||
|
||||
// How far are we going, both in steps and in mm?
|
||||
|
||||
|
@ -406,15 +512,11 @@ MovementProfile DDA::Init(float currentPosition[], float targetPosition[], float
|
|||
{
|
||||
d = targetPosition[drive] - currentPosition[drive]; //Absolute
|
||||
distance += d*d;
|
||||
delta[drive] = (long)(d*platform->DriveStepsPerUnit(drive));
|
||||
if(delta[drive])
|
||||
axesMoving |= 1<<drive;
|
||||
delta[drive] = (long)roundf(d*platform->DriveStepsPerUnit(drive));
|
||||
} else
|
||||
{
|
||||
delta[drive] = (long)(targetPosition[drive]*platform->DriveStepsPerUnit(drive)); // Relative
|
||||
delta[drive] = (long)roundf(targetPosition[drive]*platform->DriveStepsPerUnit(drive)); // Relative
|
||||
eDistance += targetPosition[drive]*targetPosition[drive];
|
||||
if(delta[drive])
|
||||
extrudersMoving |= 1<<(drive - AXES);
|
||||
}
|
||||
|
||||
if(delta[drive] >= 0)
|
||||
|
@ -429,10 +531,13 @@ MovementProfile DDA::Init(float currentPosition[], float targetPosition[], float
|
|||
totalSteps = delta[drive];
|
||||
}
|
||||
|
||||
// Not going anywhere?
|
||||
// Not going anywhere? Should have been chucked away before we got here.
|
||||
|
||||
if(totalSteps <= 0)
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "DDA.Init(): Null movement!\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set up the DDA
|
||||
|
||||
|
@ -446,48 +551,56 @@ MovementProfile DDA::Init(float currentPosition[], float targetPosition[], float
|
|||
|
||||
distance = sqrt(distance);
|
||||
|
||||
if(axesMoving & (1<<Z_AXIS)) // Z involved?
|
||||
// Decide the appropriate acceleration and instantDv values
|
||||
// timeStep is set here to the distance of the
|
||||
// corresponding axis step. It will be divided
|
||||
// by a velocity later.
|
||||
|
||||
if(delta[Z_AXIS]) // Z involved?
|
||||
{
|
||||
acceleration = platform->Acceleration(Z_AXIS);
|
||||
jerk = platform->Jerk(Z_AXIS);
|
||||
} else if(axesMoving) // X or Y involved?
|
||||
instantDv = platform->InstantDv(Z_AXIS);
|
||||
timeStep = 1.0/platform->DriveStepsPerUnit(Z_AXIS);
|
||||
} else if(delta[X_AXIS] || delta[Y_AXIS]) // X or Y involved?
|
||||
{
|
||||
acceleration = platform->Acceleration(X_AXIS);
|
||||
jerk = platform->Jerk(X_AXIS);
|
||||
instantDv = platform->InstantDv(X_AXIS);
|
||||
timeStep = 1.0/platform->DriveStepsPerUnit(X_AXIS); // Slight hack
|
||||
} else // Must be extruders only
|
||||
{
|
||||
acceleration = FLT_MAX; // Slight hack
|
||||
distance = sqrt(eDistance);
|
||||
for(drive = AXES; drive < DRIVES; drive++)
|
||||
{
|
||||
if(extrudersMoving & (1<<(drive - AXES)))
|
||||
if(delta[drive])
|
||||
{
|
||||
if(platform->Acceleration(drive) < acceleration)
|
||||
{
|
||||
acceleration = platform->Acceleration(drive);
|
||||
jerk = platform->Jerk(drive);
|
||||
instantDv = platform->InstantDv(drive);
|
||||
timeStep = 1.0/platform->DriveStepsPerUnit(drive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If velocities requested are (almost) zero, set them to the jerk
|
||||
// If velocities requested are (almost) zero, set them to instantDv
|
||||
|
||||
if(v < 0.01) // Set change here?
|
||||
v = jerk;
|
||||
v = instantDv;
|
||||
if(u < 0.01)
|
||||
u = jerk;
|
||||
u = instantDv;
|
||||
|
||||
// At which DDA step should we stop accelerating? targetPosition[DRIVES] contains
|
||||
// the desired feedrate.
|
||||
|
||||
d = 0.5*(targetPosition[DRIVES]*targetPosition[DRIVES] - u*u)/acceleration; // d = (v1^2 - v0^2)/2a
|
||||
stopAStep = (long)((d*totalSteps)/distance);
|
||||
stopAStep = (long)roundf((d*totalSteps)/distance);
|
||||
|
||||
// At which DDA step should we start decelerating?
|
||||
|
||||
d = 0.5*(v*v - targetPosition[DRIVES]*targetPosition[DRIVES])/acceleration; // This should be 0 or negative...
|
||||
startDStep = totalSteps + (long)((d*totalSteps)/distance);
|
||||
startDStep = totalSteps + (long)roundf((d*totalSteps)/distance);
|
||||
|
||||
// If acceleration stop is at or after deceleration start, then the distance moved
|
||||
// is not enough to get to full speed.
|
||||
|
@ -542,18 +655,19 @@ MovementProfile DDA::Init(float currentPosition[], float targetPosition[], float
|
|||
if(velocity <= 0.0)
|
||||
{
|
||||
velocity = 1.0;
|
||||
platform->Message(HOST_MESSAGE, "DDA.Init(): Zero or negative initial velocity!");
|
||||
platform->Message(HOST_MESSAGE, "DDA.Init(): Zero or negative initial velocity!\n");
|
||||
}
|
||||
|
||||
// How far have we gone?
|
||||
|
||||
stepCount = 0;
|
||||
|
||||
// Guess that the first DDA move will be in roughly the direction
|
||||
// recorded in axesMoving. This is a simple heuristic, and any
|
||||
// small error will be forgotten with the very next step.
|
||||
// timeStep is an axis step distance at this point; divide it by the
|
||||
// velocity to get time.
|
||||
|
||||
timeStep = move->stepDistances[axesMoving]/velocity;
|
||||
timeStep = timeStep/velocity;
|
||||
|
||||
lookAhead->Release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -563,7 +677,7 @@ 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));
|
||||
platform->SetInterrupt((long)(1.0e6*timeStep)); // microseconds
|
||||
active = true;
|
||||
}
|
||||
|
||||
|
@ -581,7 +695,26 @@ void DDA::Step(boolean noTest)
|
|||
if(counter[drive] > 0)
|
||||
{
|
||||
if(noTest)
|
||||
{
|
||||
platform->Step(drive);
|
||||
|
||||
// Hit anything?
|
||||
|
||||
if(checkEndStops)
|
||||
{
|
||||
EndStopHit esh = platform->Stopped(drive);
|
||||
if(esh == lowHit)
|
||||
{
|
||||
move->HitLowStop(drive);
|
||||
active = false;
|
||||
}
|
||||
if(esh == highHit)
|
||||
{
|
||||
move->HitHighStop(drive);
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
counter[drive] -= totalSteps;
|
||||
|
||||
if(drive < AXES)
|
||||
|
@ -591,34 +724,39 @@ void DDA::Step(boolean noTest)
|
|||
}
|
||||
}
|
||||
|
||||
// Simple Euler integration to get velocities.
|
||||
// Maybe one day do a Runge-Kutta?
|
||||
// May have hit a stop
|
||||
|
||||
if(stepCount < stopAStep)
|
||||
if(active)
|
||||
{
|
||||
if(axesMoving)
|
||||
timeStep = move->stepDistances[axesMoving]/velocity;
|
||||
else
|
||||
timeStep = move->extruderStepDistances[extrudersMoving]/velocity;
|
||||
velocity += acceleration*timeStep;
|
||||
if(noTest)
|
||||
// Simple Euler integration to get velocities.
|
||||
// Maybe one day do a Runge-Kutta?
|
||||
|
||||
if(stepCount < stopAStep)
|
||||
{
|
||||
if(axesMoving)
|
||||
timeStep = move->stepDistances[axesMoving]/velocity;
|
||||
else
|
||||
timeStep = move->extruderStepDistances[extrudersMoving]/velocity;
|
||||
velocity += acceleration*timeStep;
|
||||
if(noTest)
|
||||
platform->SetInterrupt((long)(1.0e6*timeStep));
|
||||
}
|
||||
|
||||
if(stepCount >= startDStep)
|
||||
{
|
||||
if(axesMoving)
|
||||
timeStep = move->stepDistances[axesMoving]/velocity;
|
||||
else
|
||||
timeStep = move->extruderStepDistances[extrudersMoving]/velocity;
|
||||
velocity -= acceleration*timeStep;
|
||||
if(noTest)
|
||||
platform->SetInterrupt((long)(1.0e6*timeStep));
|
||||
}
|
||||
|
||||
stepCount++;
|
||||
active = stepCount < totalSteps;
|
||||
}
|
||||
|
||||
if(stepCount >= startDStep)
|
||||
{
|
||||
if(axesMoving)
|
||||
timeStep = move->stepDistances[axesMoving]/velocity;
|
||||
else
|
||||
timeStep = move->extruderStepDistances[extrudersMoving]/velocity;
|
||||
velocity -= acceleration*timeStep;
|
||||
if(noTest)
|
||||
platform->SetInterrupt((long)(1.0e6*timeStep));
|
||||
}
|
||||
|
||||
stepCount++;
|
||||
active = stepCount < totalSteps;
|
||||
|
||||
if(!active && noTest)
|
||||
platform->SetInterrupt(STANDBY_INTERRUPT_RATE);
|
||||
}
|
||||
|
@ -632,40 +770,55 @@ LookAhead::LookAhead(Move* m, Platform* p, LookAhead* n)
|
|||
next = n;
|
||||
}
|
||||
|
||||
void LookAhead::Init(float m[], float uu, float vv)
|
||||
void LookAhead::Init(float ep[], float vv, boolean ce)
|
||||
{
|
||||
u = uu;
|
||||
v = vv;
|
||||
processed = true; // Fixme
|
||||
for(char i = 0; i <= DRIVES; i++)
|
||||
movement[i] = m[i];
|
||||
endPoint[i] = ep[i];
|
||||
|
||||
checkEndStops = ce;
|
||||
|
||||
// Cosines are lazily evaluated; flag this
|
||||
// as unevaluated
|
||||
|
||||
cosine = 2.0;
|
||||
|
||||
// Only bother with lookahead when we
|
||||
// are printing a file, so set processed
|
||||
// complete when we aren't.
|
||||
|
||||
if(reprap.GetGCodes()->PrintingAFile())
|
||||
processed = unprocessed;
|
||||
else
|
||||
processed = complete|vCosineSet|upPass;
|
||||
}
|
||||
|
||||
// This returns the cosine of the angle between
|
||||
// the movement starting at start, and the movement
|
||||
// starting at the end of that. Note that it
|
||||
// the movement up to this, and the movement
|
||||
// away from this. Note that it
|
||||
// includes Z movements, though Z values will almost always
|
||||
// not change.
|
||||
// not change. Uses lazy evaluation.
|
||||
|
||||
float LookAhead::Cosine(LookAhead* start)
|
||||
float LookAhead::Cosine()
|
||||
{
|
||||
LookAhead* n1 = start->Next();
|
||||
LookAhead* n2 = n1->Next();
|
||||
float sum = 0.0;
|
||||
if(cosine < 1.5)
|
||||
return cosine;
|
||||
|
||||
cosine = 0.0;
|
||||
float a2 = 0.0;
|
||||
float b2 = 0.0;
|
||||
float m1;
|
||||
float m2;
|
||||
for(char i = 0; i < AXES; i++)
|
||||
{
|
||||
m1 = n1->movement[i] - start->movement[i];
|
||||
m2 = n2->movement[i] - n1->movement[i];
|
||||
m1 = endPosition[i] - Previous()->endPosition[i];
|
||||
m2 = Next()->endPosition[i] - endPosition[i];
|
||||
a2 += m1*m1;
|
||||
b2 += m2*m2;
|
||||
sum += m1*m2;
|
||||
cosine += m1*m2;
|
||||
}
|
||||
sum = sum/( (float)sqrt(a2) * (float)sqrt(b2) );
|
||||
return sum;
|
||||
cosine = cosine/( (float)sqrt(a2) * (float)sqrt(b2) );
|
||||
return cosine;
|
||||
}
|
||||
|
||||
|
||||
|
|
69
Platform.h
69
Platform.h
|
@ -44,6 +44,14 @@ Licence: GPL
|
|||
#include <Arduino.h>
|
||||
|
||||
|
||||
/**************************************************************************************************/
|
||||
|
||||
// Some numbers...
|
||||
|
||||
#define CLIENT_CLOSE_DELAY 1000 // Microseconds to wait after serving a page
|
||||
#define STRING_LENGTH 1000
|
||||
|
||||
|
||||
/**************************************************************************************************/
|
||||
|
||||
// The physical capabilities of the machine
|
||||
|
@ -69,15 +77,18 @@ Licence: GPL
|
|||
#define HIGH_STOP_PINS {-1, -1, -1, -1}
|
||||
#define ENDSTOP_HIT 1 // when a stop == this it is hit
|
||||
#define MAX_FEEDRATES {300, 300, 3, 45} // mm/sec
|
||||
#define ACCELERATIONS {800, 800, 30, 250} // mm/sec^2??
|
||||
//#define ACCELERATIONS {800, 800, 30, 250} // mm/sec^2??
|
||||
#define ACCELERATIONS {80, 80, 3, 25}
|
||||
#define DRIVE_STEPS_PER_UNIT {91.4286, 91.4286, 4000, 929}
|
||||
#define JERKS {15.0, 15.0, 0.4, 15.0} // (mm/sec)
|
||||
#define INSTANT_DVS {15.0, 15.0, 0.4, 15.0} // (mm/sec)
|
||||
#define GCODE_LETTERS { 'X', 'Y', 'Z', 'E', 'F' } // The drives and feedrate in a GCode
|
||||
|
||||
// AXES
|
||||
|
||||
#define START_FEED_RATE 200.0
|
||||
|
||||
#define AXIS_LENGTHS {210, 210, 120} // mm
|
||||
#define FAST_HOME_FEEDRATES {50*60, 50*60, 1*60} // mm/min
|
||||
#define HOME_FEEDRATES {50*60, 50*60, 1*60} // mm/min
|
||||
|
||||
#define X_AXIS 0 // The index of the X axis
|
||||
#define Y_AXIS 1 // The index of the Y axis
|
||||
|
@ -117,6 +128,12 @@ Licence: GPL
|
|||
#define FILE_LIST_BRACKET '"'
|
||||
#define FILE_LIST_LENGTH 1000 // Maximum lenght of file list
|
||||
|
||||
#define FLASH_LED 'F' // Type byte of a message that is to flash an LED; the next two bytes define
|
||||
// the frequency and M/S ratio.
|
||||
#define DISPLAY_MESSAGE 'L' // Type byte of a message that is to appear on a local display; the L is
|
||||
// not displayed; \f and \n should be supported.
|
||||
#define HOST_MESSAGE 'H' // Type byte of a message that is to be sent to the host; the H is not sent.
|
||||
|
||||
/****************************************************************************************************/
|
||||
|
||||
// Networking
|
||||
|
@ -156,6 +173,13 @@ Licence: GPL
|
|||
|
||||
/****************************************************************************************************/
|
||||
|
||||
enum EndStopHit
|
||||
{
|
||||
noStop = 0,
|
||||
lowHit = 1,
|
||||
highHit = 2
|
||||
};
|
||||
|
||||
class Platform
|
||||
{
|
||||
public:
|
||||
|
@ -213,10 +237,12 @@ class Platform
|
|||
void SetDirection(byte drive, bool direction);
|
||||
void Step(byte drive);
|
||||
void Disable(byte drive); // There is no drive enable; drives get enabled automatically the first time they are used.
|
||||
void Home(byte axis);
|
||||
float DriveStepsPerUnit(char drive);
|
||||
float Acceleration(char drive);
|
||||
float Jerk(char drive);
|
||||
float InstantDv(char drive);
|
||||
float HomeFeedRate(char drive);
|
||||
EndStopHit Stopped(char drive);
|
||||
float AxisLength(char drive);
|
||||
|
||||
float ZProbe(); // Return the height above the bed. Returned value is negative if probing isn't implemented
|
||||
void ZProbe(float h); // Move to height h above the bed using the probe (if there is one). h should be non-negative.
|
||||
|
@ -257,12 +283,12 @@ class Platform
|
|||
float maxFeedrates[DRIVES];
|
||||
float accelerations[DRIVES];
|
||||
float driveStepsPerUnit[DRIVES];
|
||||
float jerks[DRIVES];
|
||||
float instantDvs[DRIVES];
|
||||
|
||||
// AXES
|
||||
|
||||
float axisLengths[AXES];
|
||||
float fastHomeFeedrates[AXES];
|
||||
float homeFeedrates[AXES];
|
||||
|
||||
// HEATERS - Bed is assumed to be the first
|
||||
|
||||
|
@ -352,9 +378,9 @@ inline float Platform::Acceleration(char drive)
|
|||
return accelerations[drive];
|
||||
}
|
||||
|
||||
inline float Platform::Jerk(char drive)
|
||||
inline float Platform::InstantDv(char drive)
|
||||
{
|
||||
return jerks[drive];
|
||||
return instantDvs[drive];
|
||||
}
|
||||
|
||||
inline void Platform::SetDirection(byte drive, bool direction)
|
||||
|
@ -369,6 +395,31 @@ inline void Platform::Step(byte drive)
|
|||
digitalWrite(stepPins[drive], 1);
|
||||
}
|
||||
|
||||
inline float Platform::HomeFeedRate(char drive)
|
||||
{
|
||||
return homeFeedrates[drive];
|
||||
}
|
||||
|
||||
inline EndStopHit Platform::Stopped(char drive)
|
||||
{
|
||||
if(lowStopPins[drive] >= 0)
|
||||
{
|
||||
if(digitalRead(lowStopPins[drive]) == ENDSTOP_HIT)
|
||||
return lowHit;
|
||||
}
|
||||
if(highStopPins[drive] >= 0)
|
||||
{
|
||||
if(digitalRead(highStopPins[drive]) == ENDSTOP_HIT)
|
||||
return highHit;
|
||||
}
|
||||
return noStop;
|
||||
}
|
||||
|
||||
inline float Platform::AxisLength(char drive)
|
||||
{
|
||||
return axisLengths[drive];
|
||||
}
|
||||
|
||||
inline int Platform::GetRawTemperature(byte heater)
|
||||
{
|
||||
return analogRead(tempSensePins[heater]);
|
||||
|
|
|
@ -81,12 +81,12 @@ void Platform::Init()
|
|||
maxFeedrates = MAX_FEEDRATES;
|
||||
accelerations = ACCELERATIONS;
|
||||
driveStepsPerUnit = DRIVE_STEPS_PER_UNIT;
|
||||
jerks = JERKS;
|
||||
instantDvs = INSTANT_DVS;
|
||||
|
||||
// AXES
|
||||
|
||||
axisLengths = AXIS_LENGTHS;
|
||||
fastHomeFeedrates = FAST_HOME_FEEDRATES;
|
||||
homeFeedrates = HOME_FEEDRATES;
|
||||
|
||||
// HEATERS - Bed is assumed to be the first
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
G1 X55 Y5 F2000
|
||||
G1 X55 Y55
|
||||
G1 X5 Y55
|
||||
G1 X5 Y5
|
||||
G1 X55 Y5
|
||||
G1 X55 Y55
|
||||
G1 X5 Y55
|
||||
G1 X5 Y5
|
||||
G1 Y55
|
||||
G1 X5
|
||||
G1 Y5
|
||||
G1 X30
|
||||
G1 X55
|
||||
G1 Y55 ; Confusing: F20
|
||||
G1 Y55
|
||||
G1 X5
|
||||
G1 Y5
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
G1 X55 Y5 F2000
|
||||
G1 Y55
|
||||
G1 X5
|
||||
G1 Y5
|
||||
G1 X30
|
||||
G1 X55
|
||||
G1 Y55
|
||||
G1 Y55
|
||||
G1 X5
|
||||
G1 Y5
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE HTML>
|
||||
<head>
|
||||
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="shortcut icon" href="https://github.com/reprappro/RepRapFirmware/raw/due/SD-image/www/favicon.ico" />
|
||||
|
||||
<style type="text/css">
|
||||
.pages
|
||||
|
@ -69,8 +69,8 @@ td { text-align: center; }
|
|||
</head>
|
||||
|
||||
<html>
|
||||
<script src="jquery.js" type="text/javascript"></script>
|
||||
<script src="knockout.js" type="text/javascript"></script>
|
||||
<script src="https://raw.github.com/reprappro/RepRapFirmware/due/SD-image/www/jquery.js" type="text/javascript"></script>
|
||||
<script src="https://raw.github.com/reprappro/RepRapFirmware/due/SD-image/www/knockout.js" type="text/javascript"></script>
|
||||
<script>
|
||||
function jogRowHTML(axis)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<!DOCTYPE HTML>
|
||||
<head>
|
||||
|
||||
<link rel="shortcut icon" href="https://github.com/reprappro/RepRapFirmware/raw/due/SD-image/www/favicon.ico" />
|
||||
|
||||
<style type="text/css">
|
||||
.pages
|
||||
{
|
||||
|
@ -67,8 +69,8 @@ td { text-align: center; }
|
|||
</head>
|
||||
|
||||
<html>
|
||||
<script src="jquery.js" type="text/javascript"></script>
|
||||
<script src="knockout.js" type="text/javascript"></script>
|
||||
<script src="https://raw.github.com/reprappro/RepRapFirmware/due/SD-image/www/jquery.js" type="text/javascript"></script>
|
||||
<script src="https://raw.github.com/reprappro/RepRapFirmware/due/SD-image/www/knockout.js" type="text/javascript"></script>
|
||||
<script>
|
||||
function jogRowHTML(axis)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,14 @@ Licence: GPL
|
|||
#define WEBSERVER_H
|
||||
|
||||
|
||||
#define INDEX_PAGE "reprap.htm"
|
||||
#define MESSAGE_FILE "messages.txt"
|
||||
#define FOUR04_FILE "html404.htm"
|
||||
#define KO_START "rr_"
|
||||
#define KO_FIRST 3
|
||||
#define POST_LENGTH 200
|
||||
#define GCODE_LENGTH 100 // Maximum lenght of internally-generated G Code string
|
||||
|
||||
class Webserver
|
||||
{
|
||||
public:
|
||||
|
|
Reference in a new issue