diff --git a/Configuration.h b/Configuration.h index 1d88b20..e80a2b2 100644 --- a/Configuration.h +++ b/Configuration.h @@ -26,17 +26,20 @@ Licence: GPL #define NAME "RepRapFirmware" #ifndef VERSION -#define VERSION "1.09r-dc42" +#define VERSION "1.09s-dc42-beta4" #endif #ifndef DATE -#define DATE "2016-01-16" +#define DATE "2016-03-08" #endif #define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman" #define FLASH_SAVE_ENABLED (1) +//#define EXTERNAL_DRIVERS (1) +//#define FIRST_EXTERNAL_DRIVE (4) + // Other firmware that we might switch to be compatible with. enum Compatibility @@ -81,9 +84,9 @@ const float HOT_ENOUGH_TO_EXTRUDE = 160.0; // Celsius const float HOT_ENOUGH_TO_RETRACT = 90.0; // Celsius const float TIME_TO_HOT = 150.0; // Seconds -const uint8_t MAX_BAD_TEMPERATURE_COUNT = 6; // Number of bad temperature samples before a heater fault is reported +const uint8_t MAX_BAD_TEMPERATURE_COUNT = 4; // Number of bad temperature samples permitted before a heater fault is reported const float BAD_LOW_TEMPERATURE = -10.0; // Celsius -const float BAD_HIGH_TEMPERATURE = 300.0; // Celsius +const float DEFAULT_TEMPERATURE_LIMIT = 300.0; // Celsius const float HOT_END_FAN_TEMPERATURE = 45.0; // Temperature at which a thermostatic hot end fan comes on const float BAD_ERROR_TEMPERATURE = 2000.0; // must exceed BAD_HIGH_TEMPERATURE diff --git a/ExternalDrivers.h b/ExternalDrivers.h new file mode 100644 index 0000000..f20245e --- /dev/null +++ b/ExternalDrivers.h @@ -0,0 +1,21 @@ +/* + * ExternalDrivers.h + * + * Created on: 23 Jan 2016 + * Author: David + */ + +#ifndef EXTERNALDRIVERS_H_ +#define EXTERNALDRIVERS_H_ + +namespace ExternalDrivers +{ + void Init(); + void SetCurrent(size_t drive, float current); + void EnableDrive(size_t drive, bool en); + uint32_t GetStatus(size_t drive); + bool SetMicrostepping(size_t drive, int microsteps, int mode); + unsigned int GetMicrostepping(size_t drive, bool& interpolation); +}; + +#endif /* EXTERNALDRIVERS_H_ */ diff --git a/GCodeBuffer.cpp b/GCodeBuffer.cpp index 2ad8d4c..a4240d5 100644 --- a/GCodeBuffer.cpp +++ b/GCodeBuffer.cpp @@ -65,12 +65,14 @@ bool GCodeBuffer::Put(char c) // Deal with line numbers and checksums if (Seen('*')) { - int csSent = GetIValue(); - int csHere = CheckSum(); - Seen('N'); + const int csSent = GetIValue(); + const int csHere = CheckSum(); if (csSent != csHere) { - snprintf(gcodeBuffer, GCODE_LENGTH, "M998 P%d", GetIValue()); + if (Seen('N')) + { + snprintf(gcodeBuffer, GCODE_LENGTH, "M998 P%d", GetIValue()); + } Init(); return true; } diff --git a/GCodes.cpp b/GCodes.cpp index 6b9560a..14454f8 100644 --- a/GCodes.cpp +++ b/GCodes.cpp @@ -3550,8 +3550,19 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) } break; + case 143: // Set temperature limit + if (gb->Seen('S')) + { + platform->SetTemperatureLimit(gb->GetFValue()); + } + else + { + reply.printf("Temperature limit is %.1fC", platform->GetTemperatureLimit()); + } + break; + case 144: // Set bed to standby -#if BED_HEATER != -1 +#if BED_HEATER >= 0 reprap.GetHeat()->Standby(BED_HEATER); #else reply.copy("Hot bed is not present!"); @@ -3559,14 +3570,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) #endif break; - // case 160: //number of mixing filament drives TODO: With tools defined, is this needed? -// if(gb->Seen('S')) -// { -// platform->SetMixingDrives(gb->GetIValue()); -// } -// break; - - case 190: // Deprecated... + case 190: // Set bed temperature and wait if (!AllMovesAreFinishedAndMoveBufferIsLoaded()) // tell Move not to wait for more moves { return false; @@ -3818,9 +3822,75 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) SetHeaterParameters(gb, reply); break; + case 350: // Set/report microstepping + if (!AllMovesAreFinishedAndMoveBufferIsLoaded()) + { + return false; + } + { + // interp is current an int not a bool, because we use special values of interp to set the chopper control register + int interp = 0; + if (gb->Seen('I')) + { + interp = gb->GetIValue(); + } + + bool seen = false; + for (size_t axis = 0; axis < AXES; axis++) + { + if (gb->Seen(axisLetters[axis])) + { + seen = true; + int microsteps = gb->GetIValue(); + if (!platform->SetMicrostepping(axis, microsteps, interp)) + { + platform->MessageF(GENERIC_MESSAGE, "Drive %c does not support %dx microstepping%s\n", + axisLetters[axis], microsteps, (interp) ? " with interpolation" : ""); + } + } + } + + if (gb->Seen(extrudeLetter)) + { + seen = true; + long eVals[DRIVES - AXES]; + size_t eCount = DRIVES - AXES; + gb->GetLongArray(eVals, eCount); + for (size_t e = 0; e < eCount; e++) + { + if (!platform->SetMicrostepping(AXES + e, (int)eVals[e], interp)) + { + platform->MessageF(GENERIC_MESSAGE, "Drive E%u does not support %dx microstepping%s\n", + e, (int)eVals[e], (interp) ? " with interpolation" : ""); + } + } + } + + if (!seen) + { + reply.copy("Microstepping - "); + for (size_t axis = 0; axis < AXES; ++axis) + { + bool interp; + int microsteps = platform->GetMicrostepping(axis, interp); + reply.catf("%c:%d%s, ", axisLetters[axis], microsteps, (interp) ? "(on)" : ""); + } + reply.cat("E"); + for (size_t drive = AXES; drive < DRIVES; drive++) + { + bool interp; + int microsteps = platform->GetMicrostepping(drive, interp); + reply.catf(":%d%s", microsteps, (interp) ? "(on)" : ""); + } + } + } + break; + case 400: // Wait for current moves to finish if (!AllMovesAreFinishedAndMoveBufferIsLoaded()) + { return false; + } break; case 404: // Filament width and nozzle diameter @@ -4610,7 +4680,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) break; #endif - case 579: // Scale Cartesian axes (for Delta configurations) + case 579: // Scale Cartesian axes (mostly for Delta configurations) { bool seen = false; for(size_t axis = 0; axis < AXES; axis++) @@ -4820,6 +4890,10 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) break; case 906: // Set/report Motor currents + if (!AllMovesAreFinishedAndMoveBufferIsLoaded()) + { + return false; + } { bool seen = false; for (size_t axis = 0; axis < AXES; axis++) @@ -4856,13 +4930,17 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) if (!seen) { - reply.printf("Axis currents (mA) - X:%d, Y:%d, Z:%d, E:", (int) platform->MotorCurrent(X_AXIS), - (int) platform->MotorCurrent(Y_AXIS), (int) platform->MotorCurrent(Z_AXIS)); + reply.copy("Axis currents (mA) - "); + for (size_t axis = 0; axis < AXES; ++axis) + { + reply.catf("%c:%d, ", axisLetters[axis], (int) platform->MotorCurrent(axis)); + } + reply.cat("E"); for (size_t drive = AXES; drive < DRIVES; drive++) { - reply.catf("%d%c", (int) platform->MotorCurrent(drive), (drive < DRIVES - 1) ? ':' : ','); + reply.catf(":%d", (int) platform->MotorCurrent(drive)); } - reply.catf(" idle factor %d", (int)(platform->GetIdleCurrentFactor() * 100.0)); + reply.catf(", idle factor %d%%", (int)(platform->GetIdleCurrentFactor() * 100.0)); } } break; diff --git a/Heat.cpp b/Heat.cpp index cebe933..ec04e87 100644 --- a/Heat.cpp +++ b/Heat.cpp @@ -163,8 +163,8 @@ void PID::Spin() // Always know our temperature, regardless of whether we have been switched on or not - Platform::TempError err = Platform::TempError::errOpen; // Initially assign an error; call should update but if it doesn't, we'll treat as an error - temperature = platform->GetTemperature(heater, &err); // In the event of an error, err is set and BAD_ERROR_TEMPERATURE is returned + Platform::TempError err = Platform::TempError::errOk; // assume no error + temperature = platform->GetTemperature(heater, &err); // in the event of an error, err is set and BAD_ERROR_TEMPERATURE is returned // If we're not switched on, or there's a fault, turn the power off and go home. // If we're not switched on, then nothing is using us. This probably means that @@ -180,7 +180,16 @@ void PID::Spin() // We are switched on. Check for faults. Temperature silly-low or silly-high mean open-circuit // or shorted thermistor respectively. - if (temperature < BAD_LOW_TEMPERATURE || temperature > BAD_HIGH_TEMPERATURE) + if (temperature < BAD_LOW_TEMPERATURE) + { + err = Platform::TempError::errOpen; + } + else if (temperature > platform->GetTemperatureLimit()) + { + err = Platform::TempError::errTooHigh; + } + + if (err != Platform::TempError::errOk) { if (platform->DoThermistorAdc(heater) || !(Platform::TempErrorPermanent(err))) { @@ -209,7 +218,7 @@ void PID::Spin() } else { - badTemperatureCount = 0; + badTemperatureCount = 0; } // Now check how long it takes to warm up. If too long, maybe the thermistor is not in contact with the heater @@ -303,6 +312,75 @@ void PID::Spin() // debugPrintf("Heater %d: e=%f, P=%f, I=%f, d=%f, r=%f\n", heater, error, pp.kP*error, temp_iState, temp_dState, result); } +void PID::SetActiveTemperature(float t) +{ + if (t > platform->GetTemperatureLimit()) + { + platform->MessageF(GENERIC_MESSAGE, "Error: Temperature %.1f too high for heater %d!\n", t, heater); + } + + SwitchOn(); + activeTemperature = t; +} + +void PID::SetStandbyTemperature(float t) +{ + if (t > platform->GetTemperatureLimit()) + { + platform->MessageF(GENERIC_MESSAGE, "Error: Temperature %.1f too high for heater %d!\n", t, heater); + } + + SwitchOn(); + standbyTemperature = t; +} + +void PID::Activate() +{ + if (temperatureFault) + { + return; + } + + SwitchOn(); + active = true; + if (!heatingUp) + { + timeSetHeating = platform->Time(); + } + heatingUp = activeTemperature > temperature; +} + +void PID::Standby() +{ + if (temperatureFault) + { + return; + } + + SwitchOn(); + active = false; + if (!heatingUp) + { + timeSetHeating = platform->Time(); + } + heatingUp = standbyTemperature > temperature; +} + +void PID::ResetFault() +{ + temperatureFault = false; + timeSetHeating = platform->Time(); // otherwise we will get another timeout immediately + badTemperatureCount = 0; +} + +void PID::SwitchOff() +{ + SetHeater(0.0); + active = false; + switchedOff = true; + heatingUp = false; +} + float PID::GetAveragePWM() const { return averagePWM * invHeatPwmAverageCount; diff --git a/Heat.h b/Heat.h index 90fd951..b2582e0 100644 --- a/Heat.h +++ b/Heat.h @@ -137,33 +137,11 @@ inline bool PID::Active() const return active; } -inline void PID::SetActiveTemperature(float t) -{ - if (t > BAD_HIGH_TEMPERATURE) - { - platform->MessageF(GENERIC_MESSAGE, "Error: Temperature %.1f too high for heater %d!\n", t, heater); - } - - SwitchOn(); - activeTemperature = t; -} - inline float PID::GetActiveTemperature() const { return activeTemperature; } -inline void PID::SetStandbyTemperature(float t) -{ - if (t > BAD_HIGH_TEMPERATURE) - { - platform->MessageF(GENERIC_MESSAGE, "Error: Temperature %.1f too high for heater %d!\n", t, heater); - } - - SwitchOn(); - standbyTemperature = t; -} - inline float PID::GetStandbyTemperature() const { return standbyTemperature; @@ -174,58 +152,11 @@ inline float PID::GetTemperature() const return temperature; } -inline void PID::Activate() -{ - if (temperatureFault) - { - return; - } - - SwitchOn(); - active = true; - if (!heatingUp) - { - timeSetHeating = platform->Time(); - } - heatingUp = activeTemperature > temperature; -} - -inline void PID::Standby() -{ - if (temperatureFault) - { - return; - } - - SwitchOn(); - active = false; - if (!heatingUp) - { - timeSetHeating = platform->Time(); - } - heatingUp = standbyTemperature > temperature; -} - inline bool PID::FaultOccurred() const { return temperatureFault; } -inline void PID::ResetFault() -{ - temperatureFault = false; - timeSetHeating = platform->Time(); // otherwise we will get another timeout immediately - badTemperatureCount = 0; -} - -inline void PID::SwitchOff() -{ - SetHeater(0.0); - active = false; - switchedOff = true; - heatingUp = false; -} - inline bool PID::SwitchedOff() const { return switchedOff; diff --git a/Libraries/SamNonDuePin/SamNonDuePin.cpp b/Libraries/SamNonDuePin/SamNonDuePin.cpp index 7b2e98f..f28eca7 100644 --- a/Libraries/SamNonDuePin/SamNonDuePin.cpp +++ b/Libraries/SamNonDuePin/SamNonDuePin.cpp @@ -85,7 +85,7 @@ extern void pinModeNonDue(uint32_t ulPin, uint32_t ulMode, uint32_t debounceCuto return; } - const PinDescription& pinDesc = (ulPin >= X0) ? nonDuePinDescription[ulPin - X0] : g_APinDescription[ulPin]; + const PinDescription& pinDesc = GetPinDescription(ulPin); if (pinDesc.ulPinType == PIO_NOT_A_PIN) { return; @@ -153,7 +153,7 @@ extern void digitalWriteNonDue(uint32_t ulPin, uint32_t ulVal) return; } - const PinDescription& pinDesc = (ulPin >= X0) ? nonDuePinDescription[ulPin - X0] : g_APinDescription[ulPin]; + const PinDescription& pinDesc = GetPinDescription(ulPin); if (pinDesc.ulPinType != PIO_NOT_A_PIN) { if (ulVal) // we make use of the fact that LOW is zero and HIGH is nonzero @@ -179,7 +179,7 @@ extern int digitalReadNonDue( uint32_t ulPin ) return LOW; } - const PinDescription& pinDesc = (ulPin >= X0) ? nonDuePinDescription[ulPin - X0] : g_APinDescription[ulPin]; + const PinDescription& pinDesc = GetPinDescription(ulPin); if (pinDesc.ulPinType == PIO_NOT_A_PIN) { return LOW ; @@ -191,7 +191,7 @@ extern int digitalReadNonDue( uint32_t ulPin ) // Build a short-form pin descriptor for a IO pin OutputPin::OutputPin(unsigned int pin) { - const PinDescription& pinDesc = (pin >= X0) ? nonDuePinDescription[pin - X0] : g_APinDescription[pin]; + const PinDescription& pinDesc = GetPinDescription(pin); pPort = pinDesc.pPort; ulPin = pinDesc.ulPin; } @@ -249,7 +249,7 @@ void analogWriteNonDue(uint32_t ulPin, uint32_t ulValue, uint16_t freq) ulValue = 255; } - const PinDescription& pinDesc = (ulPin >= X0) ? nonDuePinDescription[ulPin - X0] : g_APinDescription[ulPin]; + const PinDescription& pinDesc = GetPinDescription(ulPin); uint32_t attr = pinDesc.ulPinAttribute; if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG) { diff --git a/Libraries/SamNonDuePin/SamNonDuePin.h b/Libraries/SamNonDuePin/SamNonDuePin.h index 974c01b..775be28 100644 --- a/Libraries/SamNonDuePin/SamNonDuePin.h +++ b/Libraries/SamNonDuePin/SamNonDuePin.h @@ -84,18 +84,22 @@ public: void SetLow() const { pPort->PIO_CODR = ulPin; } }; -// struct used to hold the descriptions for the "non Arduino" pins. -// from the Arduino.h files -extern const PinDescription nonDuePinDescription[] ; -extern void pinModeNonDue(uint32_t ulPin, uint32_t ulMode, uint32_t debounceCutoff = 0); // NB only one debounce cutoff frequency can be set per PIO -extern void digitalWriteNonDue(uint32_t ulPin, uint32_t ulVal); -extern int digitalReadNonDue(uint32_t ulPin); -extern OutputPin getPioPin(uint32_t ulPin); -extern void analogWriteNonDue(uint32_t ulPin, uint32_t ulValue, uint16_t freq); -extern void analogOutputNonDue(); -extern void hsmciPinsinit(); -extern void ethPinsInit(); -extern adc_channel_num_t PinToAdcChannel(int pin); // convert an analog pin number to an ADC channel +extern const PinDescription nonDuePinDescription[]; + +inline const PinDescription& GetPinDescription(uint32_t ulPin) +{ + return (ulPin >= X0) ? nonDuePinDescription[ulPin - X0] : g_APinDescription[ulPin]; +} + +void pinModeNonDue(uint32_t ulPin, uint32_t ulMode, uint32_t debounceCutoff = 0); // NB only one debounce cutoff frequency can be set per PIO +void digitalWriteNonDue(uint32_t ulPin, uint32_t ulVal); +int digitalReadNonDue(uint32_t ulPin); +OutputPin getPioPin(uint32_t ulPin); +void analogWriteNonDue(uint32_t ulPin, uint32_t ulValue, uint16_t freq); +void analogOutputNonDue(); +void hsmciPinsinit(); +void ethPinsInit(); +adc_channel_num_t PinToAdcChannel(int pin); // convert an analog pin number to an ADC channel #endif /* SAM_NON_DUE_PIN_H */ diff --git a/Platform.cpp b/Platform.cpp index 0a7a589..9a3cbcd 100644 --- a/Platform.cpp +++ b/Platform.cpp @@ -22,6 +22,10 @@ #include "RepRapFirmware.h" #include "DueFlashStorage.h" +#ifdef EXTERNAL_DRIVERS +#include "ExternalDrivers.h" +#endif + extern char _end; extern "C" char *sbrk(int i); @@ -109,8 +113,7 @@ bool PidParameters::operator==(const PidParameters& other) const Platform::Platform() : autoSaveEnabled(false), board(DEFAULT_BOARD_TYPE), active(false), errorCodeBits(0), - fileStructureInitialised(false), tickState(0), debugCode(0), - messageString(messageStringBuffer, ARRAY_SIZE(messageStringBuffer)) + fileStructureInitialised(false), tickState(0), debugCode(0) { // Output auxOutput = new OutputStack(); @@ -148,7 +151,9 @@ void Platform::Init() SERIAL_MAIN_DEVICE.begin(baudRates[0]); SERIAL_AUX_DEVICE.begin(baudRates[1]); // this can't be done in the constructor because the Arduino port initialisation isn't complete at that point +#ifdef SERIAL_AUX2_DEVICE SERIAL_AUX2_DEVICE.begin(baudRates[2]); +#endif // Reconfigure the ADC to avoid crosstalk between channels (especially on Duet 0.8.5) adc_init(ADC, SystemCoreClock, ADC_FREQ_MIN, ADC_STARTUP_FAST); // reduce clock rate @@ -240,7 +245,11 @@ void Platform::Init() { pinModeNonDue(directionPins[drive], OUTPUT); } +#ifdef EXTERNAL_DRIVERS + if (drive < FIRST_EXTERNAL_DRIVE && enablePins[drive] >= 0) +#else if (enablePins[drive] >= 0) +#endif { pinModeNonDue(enablePins[drive], OUTPUT); } @@ -261,6 +270,10 @@ void Platform::Init() } } +#ifdef EXTERNAL_DRIVERS + ExternalDrivers::Init(); +#endif + extrusionAncilliaryPWM = 0.0; // HEATERS - Bed is assumed to be index 0 @@ -275,14 +288,8 @@ void Platform::Init() thermistorAdcChannels[heater] = PinToAdcChannel(tempSensePins[heater]); // Translate the Arduino Due Analog pin number to the SAM ADC channel number SetThermistorNumber(heater, heater); // map the thermistor straight through thermistorFilters[heater].Init(analogRead(tempSensePins[heater])); - - // Calculate and store the ADC average sum that corresponds to an overheat condition, so that we can check is quickly in the tick ISR - float thermistorOverheatResistance = nvData.pidParams[heater].GetRInf() - * exp(-nvData.pidParams[heater].GetBeta() / (BAD_HIGH_TEMPERATURE - ABS_ZERO)); - float thermistorOverheatAdcValue = (AD_RANGE_REAL + 1) * thermistorOverheatResistance - / (thermistorOverheatResistance + nvData.pidParams[heater].thermistorSeriesR); - thermistorOverheatSums[heater] = (uint32_t) (thermistorOverheatAdcValue + 0.9) * THERMISTOR_AVERAGE_READINGS; } + SetTemperatureLimit(DEFAULT_TEMPERATURE_LIMIT); InitFans(); @@ -338,6 +345,20 @@ void Platform::InvalidateFiles() } } +void Platform::SetTemperatureLimit(float t) +{ + temperatureLimit = t; + for (size_t heater = 0; heater < HEATERS; heater++) + { + // Calculate and store the ADC average sum that corresponds to an overheat condition, so that we can check it quickly in the tick ISR + float thermistorOverheatResistance = nvData.pidParams[heater].GetRInf() + * exp(-nvData.pidParams[heater].GetBeta() / (temperatureLimit - ABS_ZERO)); + float thermistorOverheatAdcValue = (AD_RANGE_REAL + 1) * thermistorOverheatResistance + / (thermistorOverheatResistance + nvData.pidParams[heater].thermistorSeriesR); + thermistorOverheatSums[heater] = (uint32_t) (thermistorOverheatAdcValue + 0.9) * THERMISTOR_AVERAGE_READINGS; + } +} + // Specify which thermistor channel a particular heater uses void Platform::SetThermistorNumber(size_t heater, size_t thermistor) //pre(heater < HEATERS && thermistor < HEATERS) @@ -781,6 +802,7 @@ void Platform::Spin() OutputBuffer *aux2OutputBuffer = aux2Output->GetFirstItem(); if (aux2OutputBuffer != nullptr) { +#ifdef SERIAL_AUX2_DEVICE size_t bytesToWrite = min(SERIAL_AUX2_DEVICE.canWrite(), aux2OutputBuffer->BytesLeft()); if (bytesToWrite > 0) { @@ -792,6 +814,9 @@ void Platform::Spin() aux2OutputBuffer = OutputBuffer::Release(aux2OutputBuffer); aux2Output->SetFirstItem(aux2OutputBuffer); } +#else + aux2OutputBuffer = OutputBuffer::Release(aux2OutputBuffer); +#endif } // Write non-blocking data to the USB line @@ -868,7 +893,11 @@ void Platform::SoftwareReset(uint16_t reason) { reason |= (uint16_t)SoftwareResetReason::inLwipSpin; } - if (!SERIAL_AUX_DEVICE.canWrite() || !SERIAL_AUX2_DEVICE.canWrite()) + if (!SERIAL_AUX_DEVICE.canWrite() +#ifdef SERIAL_AUX2_DEVICE + || !SERIAL_AUX2_DEVICE.canWrite() +#endif + ) { reason |= (uint16_t)SoftwareResetReason::inAuxOutput; // if we are resetting because we are stuck in a Spin function, record whether we are trying to send to aux } @@ -880,15 +909,6 @@ void Platform::SoftwareReset(uint16_t reason) temp.magic = SoftwareResetData::magicValue; temp.resetReason = reason; GetStackUsage(NULL, NULL, &temp.neverUsedRam); - if (reason != (uint16_t)SoftwareResetReason::user) - { - strncpy(temp.lastMessage, messageString.Pointer(), sizeof(temp.lastMessage) - 1); - temp.lastMessage[sizeof(temp.lastMessage) - 1] = 0; - } - else - { - temp.lastMessage[0] = 0; - } // Save diagnostics data to Flash and reset the software DueFlashStorage::write(SoftwareResetData::nvAddress, &temp, sizeof(SoftwareResetData)); @@ -1022,10 +1042,6 @@ void Platform::Diagnostics() { MessageF(GENERIC_MESSAGE, "Last software reset code & available RAM: 0x%04x, %u\n", temp.resetReason, temp.neverUsedRam); MessageF(GENERIC_MESSAGE, "Spinning module during software reset: %s\n", moduleName[temp.resetReason & 0x0F]); - if (temp.lastMessage[0]) - { - MessageF(GENERIC_MESSAGE, "Last message before reset: %s", temp.lastMessage); // usually ends with NL - } } } @@ -1178,7 +1194,10 @@ float Platform::GetTemperature(size_t heater, TempError* err) const else { // thermistor short circuit, return a high temperature - if (err) *err = TempError::errShort; + if (err) + { + *err = TempError::errShort; + } return BAD_ERROR_TEMPERATURE; } } @@ -1216,6 +1235,7 @@ float Platform::GetTemperature(size_t heater, TempError* err) const case TempError::errShortVcc : return "sensor circuit is shorted to the voltage rail"; case TempError::errShortGnd : return "sensor circuit is shorted to ground"; case TempError::errOpen : return "sensor circuit is open/disconnected"; + case TempError::errTooHigh: return "temperature above safety limit"; case TempError::errTimeout : return "communication error whilst reading sensor; read took too long"; case TempError::errIO: return "communication error whilst reading sensor; check sensor connections"; } @@ -1238,6 +1258,7 @@ bool Platform::AnyHeaterHot(uint16_t heaters, float t) const return false; } +// Update the heater PID parameters or thermistor resistance etc. void Platform::SetPidParameters(size_t heater, const PidParameters& params) { if (heater < HEATERS && params != nvData.pidParams[heater]) @@ -1247,6 +1268,7 @@ void Platform::SetPidParameters(size_t heater, const PidParameters& params) { WriteNvData(); } + SetTemperatureLimit(temperatureLimit); // recalculate the thermistor resistance at max allowed temperature for the tick ISR } } const PidParameters& Platform::GetPidParameters(size_t heater) const @@ -1329,11 +1351,22 @@ void Platform::EnableDrive(size_t drive) { UpdateMotorCurrent(driver); // the current may have been reduced by the idle timeout - const int pin = enablePins[driver]; - if (pin >= 0) +#ifdef EXTERNAL_DRIVERS + if (drive >= FIRST_EXTERNAL_DRIVE) { - digitalWriteNonDue(pin, enableValues[driver]); + ExternalDrivers::EnableDrive(driver - FIRST_EXTERNAL_DRIVE, true); } + else + { +#endif + const int pin = enablePins[driver]; + if (pin >= 0) + { + digitalWriteNonDue(pin, enableValues[driver]); + } +#ifdef EXTERNAL_DRIVERS + } +#endif } } } @@ -1344,12 +1377,23 @@ void Platform::DisableDrive(size_t drive) if (drive < DRIVES) { const size_t driver = driverNumbers[drive]; - const int pin = enablePins[driver]; - if (pin >= 0) +#ifdef EXTERNAL_DRIVERS + if (drive >= FIRST_EXTERNAL_DRIVE) { - digitalWriteNonDue(pin, !enableValues[driver]); + ExternalDrivers::EnableDrive(driver - FIRST_EXTERNAL_DRIVE, false); } - driveState[drive] = DriveStatus::disabled; + else + { +#endif + const int pin = enablePins[driver]; + if (pin >= 0) + { + digitalWriteNonDue(pin, !enableValues[driver]); + } + driveState[drive] = DriveStatus::disabled; +#ifdef EXTERNAL_DRIVERS + } +#endif } } @@ -1387,35 +1431,46 @@ void Platform::UpdateMotorCurrent(size_t drive) { current *= idleCurrentFactor; } - unsigned short pot = (unsigned short)((0.256*current*8.0*senseResistor + maxStepperDigipotVoltage/2)/maxStepperDigipotVoltage); - unsigned short dac = (unsigned short)((0.256*current*8.0*senseResistor + maxStepperDACVoltage/2)/maxStepperDACVoltage); const size_t driver = driverNumbers[drive]; - if (driver < 4) +#ifdef EXTERNAL_DRIVERS + if (driver >= FIRST_EXTERNAL_DRIVE) { - mcpDuet.setNonVolatileWiper(potWipes[driver], pot); - mcpDuet.setVolatileWiper(potWipes[driver], pot); + ExternalDrivers::SetCurrent(driver - FIRST_EXTERNAL_DRIVE, current); } else { - if (board == BoardType::Duet_085) +#endif + unsigned short pot = (unsigned short)((0.256*current*8.0*senseResistor + maxStepperDigipotVoltage/2)/maxStepperDigipotVoltage); + unsigned short dac = (unsigned short)((0.256*current*8.0*senseResistor + maxStepperDACVoltage/2)/maxStepperDACVoltage); + if (driver < 4) { - // Extruder 0 is on DAC channel 0 - if (driver == 4) - { - analogWrite(DAC0, dac); - } - else - { - mcpExpansion.setNonVolatileWiper(potWipes[driver-1], pot); - mcpExpansion.setVolatileWiper(potWipes[driver-1], pot); - } + mcpDuet.setNonVolatileWiper(potWipes[driver], pot); + mcpDuet.setVolatileWiper(potWipes[driver], pot); } else { - mcpExpansion.setNonVolatileWiper(potWipes[driver], pot); - mcpExpansion.setVolatileWiper(potWipes[driver], pot); - } + if (board == BoardType::Duet_085) + { + // Extruder 0 is on DAC channel 0 + if (driver == 4) + { + analogWrite(DAC0, dac); + } + else + { + mcpExpansion.setNonVolatileWiper(potWipes[driver-1], pot); + mcpExpansion.setVolatileWiper(potWipes[driver-1], pot); + } + } + else + { + mcpExpansion.setNonVolatileWiper(potWipes[driver], pot); + mcpExpansion.setVolatileWiper(potWipes[driver], pot); + } } +#ifdef EXTERNAL_DRIVERS + } +#endif } } @@ -1437,6 +1492,48 @@ void Platform::SetIdleCurrentFactor(float f) } } +// Set the microstepping, returning true if successful +bool Platform::SetMicrostepping(size_t drive, int microsteps, int mode) +{ + if (drive < DRIVES) + { +#ifdef EXTERNAL_DRIVERS + const size_t driver = driverNumbers[drive]; + if (driver >= FIRST_EXTERNAL_DRIVE) + { + return ExternalDrivers::SetMicrostepping(driver - FIRST_EXTERNAL_DRIVE, microsteps, mode); + } + else + { +#endif + // On-board drivers only support x16 microstepping. + // We ignore the interpolation on/off parameter so that e.g. M350 I1 E16:128 won't give an error if E1 supports interpolation but E0 doesn't. + return microsteps == 16; +#ifdef EXTERNAL_DRIVERS + } +#endif + } + return false; +} + +unsigned int Platform::GetMicrostepping(size_t drive, bool& interpolation) const +{ +#ifdef EXTERNAL_DRIVERS + if (drive < DRIVES) + { + const size_t driver = driverNumbers[drive]; + if (driver >= FIRST_EXTERNAL_DRIVE) + { + return ExternalDrivers::GetMicrostepping(driver - FIRST_EXTERNAL_DRIVE, interpolation); + } + } +#endif + + // On-board drivers only support x16 microstepping without interpolation + interpolation = false; + return 16; +} + // Set the physical drive (i.e. axis or extruder) number used by this driver void Platform::SetPhysicalDrive(size_t driverNumber, int8_t physicalDrive) { @@ -1513,7 +1610,7 @@ void Platform::InitFans() for (size_t i = 0; i < NUM_FANS; ++i) { // The cooling fan 0 output pin gets inverted if HEAT_ON == 0 on a Duet 0.4, 0.6 or 0.7 - fans[i].Init(COOLING_FAN_PINS[i], !HEAT_ON && board != BoardType::Duet_085); + fans[i].Init(COOLING_FAN_PINS[i], !HEAT_ON && (board == BoardType::Duet_06 || board == BoardType::Duet_07)); } if (NUM_FANS > 1) @@ -1711,6 +1808,7 @@ void Platform::Message(MessageType type, const char *message) break; case AUX2_MESSAGE: +#ifdef SERIAL_AUX2_DEVICE // Message that is to be sent to the second auxiliary device (blocking) if (!aux2Output->IsEmpty()) { @@ -1723,6 +1821,7 @@ void Platform::Message(MessageType type, const char *message) SERIAL_AUX2_DEVICE.write(message); SERIAL_AUX2_DEVICE.flush(); } +#endif break; case DISPLAY_MESSAGE: @@ -1965,10 +2064,12 @@ void Platform::ResetChannel(size_t chan) SERIAL_AUX_DEVICE.end(); SERIAL_AUX_DEVICE.begin(baudRates[1]); break; +#ifdef SERIAL_AUX2_DEVICE case 2: SERIAL_AUX2_DEVICE.end(); SERIAL_AUX2_DEVICE.begin(baudRates[2]); break; +#endif default: break; } @@ -1981,7 +2082,7 @@ void Platform::SetBoardType(BoardType bt) // Determine whether this is a Duet 0.6 or a Duet 0.8.5 board. // If it is a 0.85 board then DAC0 (AKA digital pin 67) is connected to ground via a diode and a 2.15K resistor. // So we enable the pullup (value 150K-150K) on pin 67 and read it, expecting a LOW on a 0.8.5 board and a HIGH on a 0.6 board. - // This may fail if anyone connects a load to the DAC0 pin on and Dur=et 0.6, hence we implement board selection in M115 as well. + // This may fail if anyone connects a load to the DAC0 pin on and Duet 0.6, hence we implement board selection in M115 as well. pinModeNonDue(Dac0DigitalPin, INPUT_PULLUP); board = (digitalReadNonDue(Dac0DigitalPin)) ? BoardType::Duet_06 : BoardType::Duet_085; pinModeNonDue(Dac0DigitalPin, INPUT); // turn pullup off @@ -2088,7 +2189,11 @@ bool Platform::GCodeAvailable(const SerialSource source) const return SERIAL_AUX_DEVICE.available() > 0; case SerialSource::AUX2: +#ifdef SERIAL_AUX2_DEVICE return SERIAL_AUX2_DEVICE.available() > 0; +#else + return false; +#endif } return false; @@ -2105,7 +2210,11 @@ char Platform::ReadFromSource(const SerialSource source) return static_cast(SERIAL_AUX_DEVICE.read()); case SerialSource::AUX2: +#ifdef SERIAL_AUX2_DEVICE return static_cast(SERIAL_AUX2_DEVICE.read()); +#else + return 0; +#endif } return 0; @@ -2180,7 +2289,7 @@ void Platform::Tick() // averaging. As such, the temperature reading is taken directly by Platform::GetTemperature() and // periodically called by PID::Spin() where temperature fault handling is taken care of. However, we // must guard against overly long delays between successive calls of PID::Spin(). - + // Do not call Time() here, it isn't safe. We use millis() instead. StartAdcConversion(zProbeAdcChannel); if ((millis() - reprap.GetHeat()->GetLastSampleTime(currentHeater)) > maxPidSpinDelay) { diff --git a/Platform.h b/Platform.h index 84d37cd..3f2f969 100644 --- a/Platform.h +++ b/Platform.h @@ -175,12 +175,6 @@ const uint8_t MAC_ADDRESS[6] = { 0xBE, 0xEF, 0xDE, 0xAD, 0xFE, 0xED }; /****************************************************************************************************/ -// Miscellaneous... - -const size_t messageStringLength = 256; // max length of a message chunk sent via Message or AppendMessage - -/****************************************************************************************************/ - enum class BoardType : uint8_t { Auto = 0, @@ -423,7 +417,7 @@ public: enum class DriveStatus : uint8_t { disabled, idle, enabled }; // Error results generated by GetTemperature() - enum class TempError : uint8_t { errOk, errShort, errShortVcc, errShortGnd, errOpen, errTimeout, errIO }; + enum class TempError : uint8_t { errOk, errShort, errShortVcc, errShortGnd, errOpen, errTooHigh, errTimeout, errIO }; Platform(); @@ -515,6 +509,8 @@ public: float MotorCurrent(size_t drive) const; void SetIdleCurrentFactor(float f); float GetIdleCurrentFactor() const { return idleCurrentFactor; } + bool SetMicrostepping(size_t drive, int microsteps, int mode); + unsigned int GetMicrostepping(size_t drive, bool& interpolation) const; float DriveStepsPerUnit(size_t drive) const; const float *GetDriveStepsPerUnit() const { return driveStepsPerUnit; } void SetDriveStepsPerUnit(size_t drive, float value); @@ -574,7 +570,8 @@ public: void SetThermistorNumber(size_t heater, size_t thermistor); int GetThermistorNumber(size_t heater) const; bool DoThermistorAdc(uint8_t heater) const; - MAX31855 Max31855Devices[MAX31855_DEVICES]; + void SetTemperatureLimit(float t); + float GetTemperatureLimit() const { return temperatureLimit; } static const char* TempErrorStr(TempError err); static bool TempErrorPermanent(TempError err); @@ -638,7 +635,6 @@ private: uint16_t magic; uint16_t resetReason; // this records why we did a software reset, for diagnostic purposes size_t neverUsedRam; // the amount of never used RAM at the last abnormal software reset - char lastMessage[256]; // the last known message before a software reset occurred }; struct FlashData @@ -759,11 +755,13 @@ private: Pin tempSensePins[HEATERS]; Pin heatOnPins[HEATERS]; + MAX31855 Max31855Devices[MAX31855_DEVICES]; Pin max31855CsPins[MAX31855_DEVICES]; float heatSampleTime; float standbyTemperatures[HEATERS]; float activeTemperatures[HEATERS]; float timeToHot; + float temperatureLimit; // Fans @@ -836,9 +834,6 @@ private: static uint16_t GetAdcReading(adc_channel_num_t chan); static void StartAdcConversion(adc_channel_num_t chan); - char messageStringBuffer[messageStringLength]; - StringRef messageString; - // Hotend configuration float filamentWidth; float nozzleDiameter; diff --git a/PrintMonitor.cpp b/PrintMonitor.cpp index 6964819..213b674 100644 --- a/PrintMonitor.cpp +++ b/PrintMonitor.cpp @@ -723,23 +723,27 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const const float fractionPrinted = gCodes->FractionOfFilePrinted(); if (numLayerSamples < 2 || !printingFileParsed || printingFileInfo.objectHeight == 0.0) { - return (fractionPrinted < 0.01) - ? 0.0 - : realPrintDuration * (1.0 / fractionPrinted) - realPrintDuration; + if (fractionPrinted < 0.01) + { + break; + } + return realPrintDuration * (1.0 / fractionPrinted) - realPrintDuration; } // Work out how much progress we made in the layers we have data for, and how long it took. // Can't use the first layer sample in the table because we don't know the fraction printed at the start. float duration = 0.0; - for(size_t layer = 1; layer < numLayerSamples; layer++) + for (size_t layer = 1; layer < numLayerSamples; layer++) { duration += layerDurations[layer]; } const float fractionPrintedInLayers = fileProgressPerLayer[numLayerSamples - 1] - fileProgressPerLayer[0]; - return (fractionPrintedInLayers < 0.01) - ? 0.0 - : duration * (1.0 - fractionPrinted)/fractionPrintedInLayers; + if (fractionPrintedInLayers >= 0.01) + { + return duration * (1.0 - fractionPrinted)/fractionPrintedInLayers; + } } + break; case filamentBased: { @@ -750,7 +754,7 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const #endif ) { - return 0.0; + break; } // Sum up the filament usage and the filament needed @@ -770,22 +774,35 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const } if (extrRawTotal >= totalFilamentNeeded) { - return 0.0; // Avoid division by zero, else the web interface will report AJAX errors + break; // Avoid division by zero, else the web interface will report AJAX errors } float filamentRate; - if (numLayerSamples) + if (numLayerSamples != 0) { filamentRate = 0.0; - for(size_t i = 0; i < numLayerSamples; i++) + size_t numSamples = 0; + for (size_t i = 0; i < numLayerSamples; i++) { - filamentRate += filamentUsagePerLayer[i] / layerDurations[i]; + if (layerDurations[i] > 0.0) + { + filamentRate += filamentUsagePerLayer[i] / layerDurations[i]; + ++numSamples; + } } - filamentRate /= numLayerSamples; + if (numSamples == 0) + { + break; + } + filamentRate /= numSamples; + } + else if (firstLayerDuration > 0.0) + { + filamentRate = firstLayerFilament / firstLayerDuration; } else { - filamentRate = firstLayerFilament / firstLayerDuration; + break; } return (totalFilamentNeeded - extrRawTotal) / filamentRate; diff --git a/Release/RepRapFirmware-1.09sbeta4-dc42.bin b/Release/RepRapFirmware-1.09sbeta4-dc42.bin new file mode 100644 index 0000000..109c4dd Binary files /dev/null and b/Release/RepRapFirmware-1.09sbeta4-dc42.bin differ diff --git a/Reprap.cpp b/Reprap.cpp index f8eac45..0144a23 100644 --- a/Reprap.cpp +++ b/Reprap.cpp @@ -163,7 +163,7 @@ void RepRap::Spin() { if (t->DisplayColdExtrudeWarning() && ToolWarningsAllowed()) { - platform->MessageF(GENERIC_MESSAGE, "Warning: Tool %d was not driven because its heater temperatures were not high enough\n", t->myNumber); + platform->MessageF(GENERIC_MESSAGE, "Warning: Tool %d was not driven because its temperatures were not high enough or it has a heater fault\n", t->myNumber); } } @@ -1341,37 +1341,44 @@ void RepRap::SetName(const char* nm) network->SetHostname(myName); } -// Given that we want to extrude/etract the specified extruder drives, check if they are allowed. +// Given that we want to extrude/retract the specified extruder drives, check if they are allowed. // For each disallowed one, log an error to report later and return a bit in the bitmap. // This may be called by an ISR! unsigned int RepRap::GetProhibitedExtruderMovements(unsigned int extrusions, unsigned int retractions) { - unsigned int result = 0; - Tool *tool = toolList; - while (tool != nullptr) + if (GetHeat()->ColdExtrude()) { - for (size_t driveNum = 0; driveNum < tool->DriveCount(); driveNum++) + return 0; + } + + Tool *tool = currentTool; + if (tool == nullptr) + { + // This should not happen, but if on tool is selected then don't allow any extruder movement + return extrusions | retractions; + } + + unsigned int result = 0; + for (size_t driveNum = 0; driveNum < tool->DriveCount(); driveNum++) + { + const unsigned int extruderDrive = (unsigned int)(tool->Drive(driveNum)); + const unsigned int mask = 1 << extruderDrive; + if (extrusions & mask) { - const int extruderDrive = tool->Drive(driveNum); - unsigned int mask = 1 << extruderDrive; - if (extrusions & mask) + if (!tool->ToolCanDrive(true)) { - if (!tool->ToolCanDrive(true)) - { - result |= mask; - } - } - else if (retractions & (1 << extruderDrive)) - { - if (!tool->ToolCanDrive(false)) - { - result |= mask; - } + result |= mask; + } + } + else if (retractions & mask) + { + if (!tool->ToolCanDrive(false)) + { + result |= mask; } } - - tool = tool->Next(); } + return result; } diff --git a/Tool.cpp b/Tool.cpp index 99b98f4..3de3c3c 100644 --- a/Tool.cpp +++ b/Tool.cpp @@ -1,43 +1,45 @@ /**************************************************************************************************** -RepRapFirmware - Tool + RepRapFirmware - Tool -This class implements a tool in the RepRap machine, usually (though not necessarily) an extruder. + 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. + 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 + Version 0.1 -Created on: Apr 11, 2014 + Created on: Apr 11, 2014 -Adrian Bowyer -RepRap Professional Ltd -http://reprappro.com + Adrian Bowyer + RepRap Professional Ltd + http://reprappro.com -Licence: GPL + Licence: GPL -****************************************************************************************************/ + ****************************************************************************************************/ #include "RepRapFirmware.h" Tool * Tool::freelist = nullptr; -/*static*/ Tool * Tool::Create(int toolNumber, long d[], size_t dCount, long h[], size_t hCount) +/*static*/Tool * Tool::Create(int toolNumber, long d[], size_t dCount, long h[], size_t hCount) { if (dCount > DRIVES - AXES) { - reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Error: Tool creation: attempt to use more drives than there are in the RepRap"); + reprap.GetPlatform()->Message(GENERIC_MESSAGE, + "Error: Tool creation: attempt to use more drives than there are in the RepRap"); return nullptr; } if (hCount > HEATERS) { - reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Error: Tool creation: attempt to use more heaters than there are in the RepRap"); + reprap.GetPlatform()->Message(GENERIC_MESSAGE, + "Error: Tool creation: attempt to use more heaters than there are in the RepRap"); return nullptr; } @@ -61,14 +63,14 @@ Tool * Tool::freelist = nullptr; t->mixing = false; t->displayColdExtrudeWarning = false; - for(size_t axis = 0; axis < AXES; axis++) + for (size_t axis = 0; axis < AXES; axis++) { t->offset[axis] = 0.0; } if (t->driveCount > 0) { - float r = 1.0/(float)(t->driveCount); + float r = 1.0 / (float) (t->driveCount); for (size_t drive = 0; drive < t->driveCount; drive++) { @@ -79,7 +81,7 @@ Tool * Tool::freelist = nullptr; if (t->heaterCount > 0) { - for(size_t heater = 0; heater < t->heaterCount; heater++) + for (size_t heater = 0; heater < t->heaterCount; heater++) { t->heaters[heater] = h[heater]; t->activeTemperatures[heater] = ABS_ZERO; @@ -90,7 +92,7 @@ Tool * Tool::freelist = nullptr; return t; } -/*static*/ void Tool::Delete(Tool *t) +/*static*/void Tool::Delete(Tool *t) { if (t != nullptr) { @@ -116,12 +118,11 @@ void Tool::Print(StringRef& reply) comma = ','; for (size_t heater = 0; heater < heaterCount; heater++) { - if (heater >= heaterCount - 1) - { - comma = ';'; - } - reply.catf("%d (%.1f/%.1f)%c", heaters[heater], - activeTemperatures[heater], standbyTemperatures[heater], comma); + if (heater >= heaterCount - 1) + { + comma = ';'; + } + reply.catf("%d (%.1f/%.1f)%c", heaters[heater], activeTemperatures[heater], standbyTemperatures[heater], comma); } reply.catf(" status: %s", active ? "selected" : "standby"); @@ -131,7 +132,8 @@ float Tool::MaxFeedrate() const { if (driveCount <= 0) { - reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Error: Attempt to get maximum feedrate for a tool with no drives.\n"); + reprap.GetPlatform()->Message(GENERIC_MESSAGE, + "Error: Attempt to get maximum feedrate for a tool with no drives.\n"); return 1.0; } float result = 0.0; @@ -173,7 +175,7 @@ float Tool::InstantDv() const void Tool::FlagTemperatureFault(int8_t heater) { Tool* n = this; - while(n != nullptr) + while (n != nullptr) { n->SetTemperatureFault(heater); n = n->Next(); @@ -183,7 +185,7 @@ void Tool::FlagTemperatureFault(int8_t heater) void Tool::ClearTemperatureFault(int8_t heater) { Tool* n = this; - while(n != nullptr) + while (n != nullptr) { n->ResetTemperatureFault(heater); n = n->Next(); @@ -194,7 +196,7 @@ void Tool::SetTemperatureFault(int8_t dudHeater) { for (size_t heater = 0; heater < heaterCount; heater++) { - if(dudHeater == heaters[heater]) + if (dudHeater == heaters[heater]) { heaterFault = true; return; @@ -269,12 +271,12 @@ void Tool::SetVariables(const float* standby, const float* active) } else { - if (active[heater] < BAD_HIGH_TEMPERATURE) + if (active[heater] < reprap.GetPlatform()->GetTemperatureLimit()) { activeTemperatures[heater] = active[heater]; reprap.GetHeat()->SetActiveTemperature(heaters[heater], activeTemperatures[heater]); } - if (standby[heater] < BAD_HIGH_TEMPERATURE) + if (standby[heater] < reprap.GetPlatform()->GetTemperatureLimit()) { standbyTemperatures[heater] = standby[heater]; reprap.GetHeat()->SetStandbyTemperature(heaters[heater], standbyTemperatures[heater]); @@ -295,11 +297,10 @@ void Tool::GetVariables(float* standby, float* active) const // May be called from ISR bool Tool::ToolCanDrive(bool extrude) { - if (heaterFault) - return false; - - if (reprap.GetHeat()->ColdExtrude() || AllHeatersAtHighTemperature(extrude)) + if (!heaterFault && AllHeatersAtHighTemperature(extrude)) + { return true; + } displayColdExtrudeWarning = true; return false; diff --git a/Webserver.cpp b/Webserver.cpp index 149cf7d..f71db6e 100644 --- a/Webserver.cpp +++ b/Webserver.cpp @@ -96,8 +96,8 @@ //*************************************************************************************************** -static const char* overflowResponse = "overflow"; -static const char* badEscapeResponse = "bad escape"; +const char* overflowResponse = "overflow"; +const char* badEscapeResponse = "bad escape"; //********************************************************************************************