diff --git a/.gitignore b/.gitignore index e8ba8b0..c9f632e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ *.d *.o -.* Release/* !Release/RepRapFirmware*.bin *~ *orig /Release + diff --git a/.gitignore.BACKUP.5284.gitignore b/.gitignore.BACKUP.5284.gitignore deleted file mode 100644 index 4592b2f..0000000 --- a/.gitignore.BACKUP.5284.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.d -*.o -Release/* -<<<<<<< HEAD -!Release/RepRapFirmware.bin -======= -!Release/RepRapFirmware*.bin ->>>>>>> duet -*~ -*orig -/Release diff --git a/.gitignore.BASE.5284.gitignore b/.gitignore.BASE.5284.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/.gitignore.LOCAL.5284.gitignore b/.gitignore.LOCAL.5284.gitignore deleted file mode 100644 index fee10ee..0000000 --- a/.gitignore.LOCAL.5284.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.d -*.o -Release/* -!Release/RepRapFirmware.bin -*~ -*orig -/Release diff --git a/.gitignore.REMOTE.5284.gitignore b/.gitignore.REMOTE.5284.gitignore deleted file mode 100644 index fccb4e4..0000000 --- a/.gitignore.REMOTE.5284.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.d -*.o -Release/* -!Release/RepRapFirmware*.bin -*~ -*orig -/Release diff --git a/Configuration.h b/Configuration.h index 3eb847c..82204dc 100644 --- a/Configuration.h +++ b/Configuration.h @@ -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 diff --git a/GCodes.cpp b/GCodes.cpp index eb1207e..9af5d75 100644 --- a/GCodes.cpp +++ b/GCodes.cpp @@ -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; diff --git a/Platform.cpp b/Platform.cpp index 89bdedb..5ea7506 100644 --- a/Platform.cpp +++ b/Platform.cpp @@ -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; } diff --git a/Platform.h b/Platform.h index a465873..b79f0f9 100644 --- a/Platform.h +++ b/Platform.h @@ -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; diff --git a/Release/RepRapFirmware-060-20-02-2014.bin b/Release/RepRapFirmware-064-11-04-2014.bin similarity index 66% rename from Release/RepRapFirmware-060-20-02-2014.bin rename to Release/RepRapFirmware-064-11-04-2014.bin index e7f26fd..c7b5f3e 100755 Binary files a/Release/RepRapFirmware-060-20-02-2014.bin and b/Release/RepRapFirmware-064-11-04-2014.bin differ diff --git a/RepRapFirmware.cpp b/RepRapFirmware.cpp index a5e82c1..bfff00c 100644 --- a/RepRapFirmware.cpp +++ b/RepRapFirmware.cpp @@ -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); +} + + //************************************************************************************************* diff --git a/RepRapFirmware.h b/RepRapFirmware.h index 27e8749..aea0608 100644 --- a/RepRapFirmware.h +++ b/RepRapFirmware.h @@ -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" diff --git a/Reprap.h b/Reprap.h index 223765c..d9f1544 100644 --- a/Reprap.h +++ b/Reprap.h @@ -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 diff --git a/Tool.cpp b/Tool.cpp new file mode 100644 index 0000000..1988db5 --- /dev/null +++ b/Tool.cpp @@ -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]); + } +} + + diff --git a/Tool.h b/Tool.h new file mode 100644 index 0000000..adad081 --- /dev/null +++ b/Tool.h @@ -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_ */ diff --git a/t b/t deleted file mode 100644 index 0d13f3a..0000000 --- a/t +++ /dev/null @@ -1 +0,0 @@ -Ormerod 3D Printer Kit without self-printed parts