Merge remote-tracking branch 'upstream/duet' into duet

Conflicts:
	GCodes.cpp
This commit is contained in:
Tony 2014-04-14 15:46:12 -04:00
commit 9623a20827
16 changed files with 387 additions and 84 deletions

2
.gitignore vendored
View file

@ -1,8 +1,8 @@
*.d
*.o
.*
Release/*
!Release/RepRapFirmware*.bin
*~
*orig
/Release

View file

@ -1,11 +0,0 @@
*.d
*.o
Release/*
<<<<<<< HEAD
!Release/RepRapFirmware.bin
=======
!Release/RepRapFirmware*.bin
>>>>>>> duet
*~
*orig
/Release

View file

@ -1,7 +0,0 @@
*.d
*.o
Release/*
!Release/RepRapFirmware.bin
*~
*orig
/Release

View file

@ -1,7 +0,0 @@
*.d
*.o
Release/*
!Release/RepRapFirmware*.bin
*~
*orig
/Release

View file

@ -24,8 +24,8 @@ Licence: GPL
#define CONFIGURATION_H
#define NAME "RepRapFirmware"
#define VERSION "0.60"
#define DATE "2014-02-20"
#define VERSION "0.64"
#define DATE "2014-04-11"
#define LAST_AUTHOR "reprappro"
// Other firmware that we might switch to be compatible with.
@ -54,7 +54,7 @@ enum Compatibility
// If temperatures fall outside this range, something
// nasty has happened.
#define BAD_LOW_TEMPERATURE -30.0
#define BAD_LOW_TEMPERATURE -10.0
#define BAD_HIGH_TEMPERATURE 300.0
#define MAX_BAD_TEMPERATURE_COUNT 6

View file

@ -989,6 +989,8 @@ void GCodes::WriteGCodeToFile(GCodeBuffer *gb)
void GCodes::QueueFileToPrint(const char* fileName)
{
if(fileToPrint != NULL)
fileToPrint->Close();
fileToPrint = platform->GetFileStore(platform->GetGCodeDir(), fileName, false);
if(fileToPrint == NULL)
{
@ -1511,7 +1513,7 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
reprap.SetDebug(gb->GetIValue());
break;
case 112: // Emergency stop - acted upon in Webserver
case 112: // Emergency stop - acted upon in Webserver, but also here in case it comes from USB etc.
reprap.EmergencyStop();
break;

View file

@ -88,8 +88,8 @@ void Platform::Init()
fileStructureInitialised = true;
mcp.begin();
mcpDuet.begin(); //only call begin once in the entire execution, this begins the I2C comms on that channel for all objects
mcpExpansion.setMCP4461Address(0x2E); //not required for mcpDuet, as this uses the default address
sysDir = SYS_DIR;
configFile = CONFIG_FILE;
@ -204,6 +204,7 @@ void Platform::Init()
if(heatOnPins[i] >= 0)
pinModeNonDue(heatOnPins[i], OUTPUT);
thermistorInfRs[i] = ( thermistorInfRs[i]*exp(-thermistorBetas[i]/(25.0 - ABS_ZERO)) );
tempSum[i] = 0;
}
if(coolingFanPin >= 0)
@ -224,15 +225,11 @@ void Platform::Init()
void Platform::InitZProbe()
{
zProbeCount = 0;
zModOnThisTime = true;
zProbeOnSum = 0;
zProbeOffSum = 0;
for (uint8_t i = 0; i < NumZProbeReadingsAveraged; ++i)
{
zProbeReadings[i] = 0;
}
if (zProbeType != 0)
if (zProbeType == 2)
{
pinMode(zProbeModulationPin, OUTPUT);
digitalWrite(zProbeModulationPin, HIGH); // enable the IR LED
@ -252,9 +249,10 @@ void Platform::Spin()
network->Spin();
line->Spin();
if(Time() - lastTime < 0.006)
if(Time() - lastTime < POLL_TIME)
return;
PollZHeight();
PollTemperatures();
lastTime = Time();
ClassReport("Platform", longWait);
@ -363,15 +361,18 @@ void Platform::ClassReport(char* className, float &lastTime)
float Platform::GetTemperature(int8_t heater)
{
// If the ADC reading is N then for an ideal ADC, the input voltage is at least N/(AD_RANGE + 1) and less than (N + 1)/(AD_RANGE + 1), times the analog reference.
// So we add 0.5 to to the reading to get a better estimate of the input. But first, recognise the special case of thermistor disconnected.
int rawTemp = GetRawTemperature(heater);
if (rawTemp == AD_RANGE)
{
// Thermistor is disconnected
return ABS_ZERO;
}
// So we add 0.5 to to the reading to get a better estimate of the input.
int rawTemp = tempSum[heater]/NUMBER_OF_A_TO_D_READINGS_AVERAGED; //GetRawTemperature(heater);
// First, recognise the special case of thermistor disconnected.
// if (rawTemp == AD_RANGE)
// {
// // Thermistor is disconnected
// return ABS_ZERO;
// }
float r = (float)rawTemp + 0.5;
return ABS_ZERO + thermistorBetas[heater]/log( (r*thermistorSeriesRs[heater]/((AD_RANGE + 1) - r))/thermistorInfRs[heater] );
r = ABS_ZERO + thermistorBetas[heater]/log( (r*thermistorSeriesRs[heater]/((AD_RANGE + 1) - r))/thermistorInfRs[heater] );
return r;
}

View file

@ -88,6 +88,10 @@ Licence: GPL
#define LOW_STOP_PINS {11, -1, 60, 31}
#define HIGH_STOP_PINS {-1, 28, -1, -1}
#define ENDSTOP_HIT 1 // when a stop == this it is hit
// Indices for motor current digipots (if any)
// first 4 are for digipot 1,(on duet)
// second 4 for digipot 2(on expansion board)
// Full order is {1, 3, 2, 0, 1, 3, 2, 0}, only include as many as you have DRIVES defined
#define POT_WIPES {1, 3, 2, 0} // Indices for motor current digipots (if any)
#define SENSE_RESISTOR 0.1 // Stepper motor current sense resistor (ohms)
#define MAX_STEPPER_DIGIPOT_VOLTAGE ( 3.3*2.5/(2.7+2.5) ) // Stepper motor current reference voltage
@ -136,6 +140,11 @@ Licence: GPL
#define AD_RANGE 1023.0 //16383 // The A->D converter that measures temperatures gives an int this big as its max value
#define NUMBER_OF_A_TO_D_READINGS_AVERAGED 8 // must be an even number, preferably a power of 2 for performance, and no greater than 64
// We hope that the compiler is clever enough to spot that division by this is a >> operation, but it doesn't really matter
#define POLL_TIME 0.006 // Poll the A to D converters this often (seconds)
#define HOT_BED 0 // The index of the heated bed; set to -1 if there is no heated bed
/****************************************************************************************************/
@ -189,7 +198,6 @@ const unsigned int httpOutputBufferSize = 2 * 1432;
#define BAUD_RATE 115200 // Communication speed of the USB if needed.
const uint16_t lineBufsize = 256; // use a power of 2 for good performance
const uint16_t NumZProbeReadingsAveraged = 8; // must be an even number, preferably a power of 2 for performance, and no greater than 64
/****************************************************************************************************/
@ -536,22 +544,23 @@ class Platform
float accelerations[DRIVES];
float driveStepsPerUnit[DRIVES];
float instantDvs[DRIVES];
MCP4461 mcp;
MCP4461 mcpDuet;
MCP4461 mcpExpansion;
int8_t potWipes[DRIVES];
float senseResistor;
float maxStepperDigipotVoltage;
// float zProbeGradient;
// float zProbeConstant;
int8_t zProbePin;
int8_t zProbeModulationPin;
int8_t zProbeType;
uint8_t zProbeCount;
bool zModOnThisTime;
long zProbeOnSum; // sum of readings taken when IR led is on
long zProbeOffSum; // sum of readings taken when IR led is on
uint16_t zProbeReadings[NumZProbeReadingsAveraged];
int zProbeADValue;
float zProbeStopHeight;
bool zProbeEnable;
// AXES
void InitZProbe();
@ -560,14 +569,13 @@ class Platform
float axisLengths[AXES];
float homeFeedrates[AXES];
float headOffsets[AXES]; // FIXME - needs a 2D array
// bool zProbeStarting;
// float zProbeHigh;
// float zProbeLow;
// HEATERS - Bed is assumed to be the first
int GetRawTemperature(byte heater) const;
void PollTemperatures();
long tempSum[HEATERS];
int8_t tempSensePins[HEATERS];
int8_t heatOnPins[HEATERS];
float thermistorBetas[HEATERS];
@ -585,7 +593,6 @@ class Platform
float standbyTemperatures[HEATERS];
float activeTemperatures[HEATERS];
int8_t coolingFanPin;
//int8_t turnHeatOn;
// Serial/USB
@ -775,8 +782,16 @@ inline void Platform::SetMotorCurrent(byte drive, float current)
// snprintf(scratchString, STRING_LENGTH, "%d", pot);
// Message(HOST_MESSAGE, scratchString);
// Message(HOST_MESSAGE, "\n");
mcp.setNonVolatileWiper(potWipes[drive], pot);
mcp.setVolatileWiper(potWipes[drive], pot);
if(drive < 4)
{
mcpDuet.setNonVolatileWiper(potWipes[drive], pot);
mcpDuet.setVolatileWiper(potWipes[drive], pot);
}
else
{
mcpExpansion.setNonVolatileWiper(potWipes[drive], pot);
mcpExpansion.setVolatileWiper(potWipes[drive], pot);
}
}
inline float Platform::HomeFeedRate(int8_t axis) const
@ -814,21 +829,41 @@ inline int Platform::GetRawZHeight() const
return (zProbeType != 0) ? analogRead(zProbePin) : 0;
}
inline void Platform::PollZHeight()
{
uint16_t currentReading = GetRawZHeight();
// We do a moving average of the probe's A to D readings to smooth out noise
if (zModOnThisTime)
zProbeOnSum = zProbeOnSum + currentReading - zProbeOnSum/NUMBER_OF_A_TO_D_READINGS_AVERAGED;
else
zProbeOffSum = zProbeOffSum + currentReading - zProbeOffSum/NUMBER_OF_A_TO_D_READINGS_AVERAGED;
if (zProbeType == 2)
{
zModOnThisTime = !zModOnThisTime;
// Reverse the modulation, ready for next time
digitalWrite(zProbeModulationPin, zModOnThisTime ? HIGH : LOW);
} else
zModOnThisTime = true; // Defensive...
}
inline int Platform::ZProbe() const
{
return (zProbeType == 1)
? (zProbeOnSum + zProbeOffSum)/NumZProbeReadingsAveraged // non-modulated mode
? zProbeOnSum/NUMBER_OF_A_TO_D_READINGS_AVERAGED // non-modulated mode
: (zProbeType == 2)
? (zProbeOnSum - zProbeOffSum)/(NumZProbeReadingsAveraged/2) // modulated mode
? (zProbeOnSum - zProbeOffSum)/NUMBER_OF_A_TO_D_READINGS_AVERAGED // modulated mode
: 0; // z-probe disabled
}
inline int Platform::ZProbeOnVal() const
{
return (zProbeType == 1)
? (zProbeOnSum + zProbeOffSum)/NumZProbeReadingsAveraged
? zProbeOnSum/NUMBER_OF_A_TO_D_READINGS_AVERAGED
: (zProbeType == 2)
? zProbeOnSum/(NumZProbeReadingsAveraged/2)
? zProbeOnSum/NUMBER_OF_A_TO_D_READINGS_AVERAGED
: 0;
}
@ -858,25 +893,7 @@ inline int Platform::GetZProbeType() const
return zProbeType;
}
inline void Platform::PollZHeight()
{
uint16_t currentReading = GetRawZHeight();
if (zProbeType == 2)
{
// Reverse the modulation, ready for next time
digitalWrite(zProbeModulationPin, (zProbeCount & 1) ? HIGH : LOW);
}
if (zProbeCount & 1)
{
zProbeOffSum = zProbeOffSum - zProbeReadings[zProbeCount] + currentReading;
}
else
{
zProbeOnSum = zProbeOnSum - zProbeReadings[zProbeCount] + currentReading;
}
zProbeReadings[zProbeCount] = currentReading;
zProbeCount = (zProbeCount + 1) % NumZProbeReadingsAveraged;
}
//********************************************************************************************************
@ -890,6 +907,14 @@ inline int Platform::GetRawTemperature(byte heater) const
return 0;
}
inline void Platform::PollTemperatures()
{
// We do a moving average of each thermometer's A to D readings to smooth out noise
for(int8_t heater = 0; heater < HEATERS; heater++)
tempSum[heater] = tempSum[heater] + GetRawTemperature(heater) - tempSum[heater]/NUMBER_OF_A_TO_D_READINGS_AVERAGED;
}
inline float Platform::HeatSampleTime() const
{
return heatSampleTime;

View file

@ -164,6 +164,7 @@ RepRap::RepRap() : active(false), debug(false)
gCodes = new GCodes(platform, webserver);
move = new Move(platform, gCodes);
heat = new Heat(platform, gCodes);
toolList = NULL;
}
void RepRap::Init()
@ -174,6 +175,7 @@ void RepRap::Init()
webserver->Init();
move->Init();
heat->Init();
currentTool = NULL;
active = true;
platform->Message(HOST_MESSAGE, NAME);
@ -193,6 +195,9 @@ void RepRap::Init()
platform->Message(HOST_MESSAGE, "\n");
platform->Message(HOST_MESSAGE, NAME);
platform->Message(HOST_MESSAGE, " is up and running.\n");
fastLoop = FLT_MAX;
slowLoop = 0.0;
lastTime = platform->Time();
}
void RepRap::Exit()
@ -216,6 +221,16 @@ void RepRap::Spin()
gCodes->Spin();
move->Spin();
heat->Spin();
// Keep track of the loop time
double t = platform->Time();
double dt = t - lastTime;
if(dt < fastLoop)
fastLoop = dt;
if(dt > slowLoop)
slowLoop = dt;
lastTime = t;
}
void RepRap::Diagnostics()
@ -225,6 +240,10 @@ void RepRap::Diagnostics()
heat->Diagnostics();
gCodes->Diagnostics();
webserver->Diagnostics();
snprintf(scratchString, STRING_LENGTH, "Slow loop secs: %f; fast: %f\n", slowLoop, fastLoop);
platform->Message(HOST_MESSAGE, scratchString);
fastLoop = FLT_MAX;
slowLoop = 0.0;
}
// Turn off the heaters, disable the motors, and
@ -237,6 +256,13 @@ void RepRap::EmergencyStop()
//platform->DisableInterrupts();
Tool* t = toolList;
while(t)
{
t->Standby();
t = t->Next();
}
heat->Exit();
for(i = 0; i < HEATERS; i++)
platform->SetHeater(i, 0.0);
@ -255,10 +281,90 @@ void RepRap::EmergencyStop()
platform->Disable(i);
}
}
platform->Message(HOST_MESSAGE, "Emergency Stop! Reset the controller to continue.");
webserver->HandleReply("Emergency Stop! Reset the controller to continue.", false);
}
void RepRap::AddTool(Tool* t)
{
if(toolList == NULL)
{
toolList = t;
return;
}
toolList->AddTool(t);
}
void RepRap::SelectTool(int toolNumber)
{
Tool* t = toolList;
while(t)
{
if(t->Number() == toolNumber)
{
t->Activate(currentTool);
currentTool = t;
return;
}
t = t->Next();
}
platform->Message(HOST_MESSAGE, "Attempt to select and activate a non-existent tool.\n");
}
void RepRap::StandbyTool(int toolNumber)
{
Tool* t = toolList;
while(t)
{
if(t->Number() == toolNumber)
{
t->Standby();
if(currentTool == t)
currentTool = NULL;
return;
}
t = t->Next();
}
platform->Message(HOST_MESSAGE, "Attempt to standby a non-existent tool.\n");
}
void RepRap::SetToolVariables(int toolNumber, float x, float y, float z, float* standbyTemperatures, float* activeTemperatures)
{
Tool* t = toolList;
while(t)
{
if(t->Number() == toolNumber)
{
t->SetVariables(x, y, z, standbyTemperatures, activeTemperatures);
return;
}
t = t->Next();
}
platform->Message(HOST_MESSAGE, "Attempt to set-up a non-existent tool.\n");
}
void RepRap::GetCurrentToolOffset(float& x, float& y, float& z)
{
if(currentTool == NULL)
{
platform->Message(HOST_MESSAGE, "Attempt to get offset when no tool selected.\n");
x = 0.0;
y = 0.0;
z = 0.0;
return;
}
currentTool->GetOffset(x, y, z);
}
//*************************************************************************************************

View file

@ -29,6 +29,7 @@ class Webserver;
class GCodes;
class Move;
class Heat;
class Tool;
class RepRap;
// A single instance of the RepRap class contains all the others
@ -56,6 +57,7 @@ extern char scratchString[];
#include "GCodes.h"
#include "Move.h"
#include "Heat.h"
#include "Tool.h"
#include "Reprap.h"

View file

@ -34,6 +34,11 @@ class RepRap
void Diagnostics();
bool Debug() const;
void SetDebug(bool d);
void AddTool(Tool* t);
void SelectTool(int toolNumber);
void StandbyTool(int toolNumber);
void SetToolVariables(int toolNumber, float x, float y, float z, float* standbyTemperatures, float* activeTemperatures);
void GetCurrentToolOffset(float& x, float& y, float& z);
Platform* GetPlatform() const;
Move* GetMove() const;
Heat* GetHeat() const;
@ -48,7 +53,11 @@ class RepRap
Heat* heat;
GCodes* gCodes;
Webserver* webserver;
Tool* toolList;
Tool* currentTool;
bool debug;
float fastLoop, slowLoop;
float lastTime;
};
inline Platform* RepRap::GetPlatform() const { return platform; }
@ -75,7 +84,6 @@ inline void RepRap::SetDebug(bool d)
inline void RepRap::Interrupt() { move->Interrupt(); }
#endif

107
Tool.cpp Normal file
View file

@ -0,0 +1,107 @@
/****************************************************************************************************
RepRapFirmware - Tool
This class implements a tool in the RepRap machine, usually (though not necessarily) an extruder.
Tools may have zero or more drives associated with them and zero or more heaters. There are a fixed number
of tools in a given RepRap, with fixed heaters and drives. All this is specified on reboot, and cannot
be altered dynamically. This restriction may be lifted in the future. Tool descriptions are stored in
GCode macros that are loaded on reboot.
-----------------------------------------------------------------------------------------------------
Version 0.1
Created on: Apr 11, 2014
Adrian Bowyer
RepRap Professional Ltd
http://reprappro.com
Licence: GPL
****************************************************************************************************/
#include "RepRapFirmware.h"
Tool::Tool(int tNum, int d[], int h[])
{
myNumber = tNum;
next = NULL;
active = false;
for(driveCount = 0; driveCount < DRIVES; driveCount++)
if(d[driveCount] < 0)
break;
if(driveCount > 0)
{
drives = new int[driveCount];
for(int8_t drive = 0; drive < driveCount; drive++)
drives[drive] = d[drive];
}
for(heaterCount = 0; heaterCount < HEATERS; heaterCount++)
if(h[heaterCount] < 0)
break;
if(heaterCount > 0)
{
heaters = new int[heaterCount];
for(int8_t heater = 0; heater < heaterCount; heater++)
heaters[heater] = h[heater];
}
x = 0.0;
y = 0.0;
z = 0.0;
}
// Add a tool to the end of the linked list.
// (We must already be in it.)
void Tool::AddTool(Tool* t)
{
Tool* last = this;
Tool* n = next;
while(n)
{
last = n;
n = Next();
}
t->next = NULL; // Defensive...
last->next = t;
}
void Tool::Activate(Tool* currentlyActive)
{
if(active)
return;
if(currentlyActive)
currentlyActive->Standby();
for(int8_t heater = 0; heater < heaterCount; heater++)
reprap.GetHeat()->Activate(heaters[heater]);
active = true;
}
void Tool::Standby()
{
if(!active)
return;
for(int8_t heater = 0; heater < heaterCount; heater++)
reprap.GetHeat()->Standby(heaters[heater]);
active = false;
}
void Tool::SetVariables(float xx, float yy, float zz, float* standbyTemperatures, float* activeTemperatures)
{
x = xx;
y = yy;
z = zz;
for(int8_t heater = 0; heater < heaterCount; heater++)
{
reprap.GetHeat()->SetActiveTemperature(heaters[heater], activeTemperatures[heater]);
reprap.GetHeat()->SetStandbyTemperature(heaters[heater], standbyTemperatures[heater]);
}
}

78
Tool.h Normal file
View file

@ -0,0 +1,78 @@
/****************************************************************************************************
RepRapFirmware - Tool
This class implements a tool in the RepRap machine, usually (though not necessarily) an extruder.
Tools may have zero or more drives associated with them and zero or more heaters. There are a fixed number
of tools in a given RepRap, with fixed heaters and drives. All this is specified on reboot, and cannot
be altered dynamically. This restriction may be lifted in the future. Tool descriptions are stored in
GCode macros that are loaded on reboot.
-----------------------------------------------------------------------------------------------------
Version 0.1
Created on: Apr 11, 2014
Adrian Bowyer
RepRap Professional Ltd
http://reprappro.com
Licence: GPL
****************************************************************************************************/
#ifndef TOOL_H_
#define TOOL_H_
class Tool
{
public:
Tool(int tNum, int d[], int h[]);
friend class RepRap;
protected:
Tool* Next();
int Number();
void Activate(Tool* currentlyActive);
void Standby();
void AddTool(Tool* t);
void SetVariables(float xx, float yy, float zz, float* standbyTemperatures, float* activeTemperatures);
void GetOffset(float& xx, float& yy, float& zz);
private:
int myNumber;
int* drives;
int driveCount;
int* heaters;
int heaterCount;
Tool* next;
float x, y, z;
bool active;
};
inline Tool* Tool::Next()
{
return next;
}
inline int Tool::Number()
{
return myNumber;
}
inline void Tool::GetOffset(float& xx, float& yy, float& zz)
{
xx = x;
yy = y;
zz = z;
}
#endif /* TOOL_H_ */

1
t
View file

@ -1 +0,0 @@
Ormerod 3D Printer Kit without self-printed parts