Version 1.09s beta 4
Enhancements: - Implemented M143 and M350 - Wait until movement finished when processing M906 - Allow for additional axes in M906 reporting code - Added support for external drivers module - Aux2 device support is now conditional - Added separate error code for temperature above safety limit Bug fixes: - Fixed spurious error report when processing corrupt input line - When there is a temperature error, return the correct error code - Update the overheat ADC value when changing thermistor parameters - Fixed occasional divide by zero problem in PrintMonitor that led to AJAX errors - Cold extrusion prevention only checks the active tool, to allow the same extruder and heater to be configured in multiple tools - If extrusion is prevented because of a temperature fault, display a message instead of silently preventing extrusion
This commit is contained in:
parent
a5722accc7
commit
bac9eb516e
15 changed files with 498 additions and 252 deletions
|
@ -26,17 +26,20 @@ Licence: GPL
|
||||||
#define NAME "RepRapFirmware"
|
#define NAME "RepRapFirmware"
|
||||||
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
#define VERSION "1.09r-dc42"
|
#define VERSION "1.09s-dc42-beta4"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DATE
|
#ifndef DATE
|
||||||
#define DATE "2016-01-16"
|
#define DATE "2016-03-08"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman"
|
#define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman"
|
||||||
|
|
||||||
#define FLASH_SAVE_ENABLED (1)
|
#define FLASH_SAVE_ENABLED (1)
|
||||||
|
|
||||||
|
//#define EXTERNAL_DRIVERS (1)
|
||||||
|
//#define FIRST_EXTERNAL_DRIVE (4)
|
||||||
|
|
||||||
// Other firmware that we might switch to be compatible with.
|
// Other firmware that we might switch to be compatible with.
|
||||||
|
|
||||||
enum Compatibility
|
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 HOT_ENOUGH_TO_RETRACT = 90.0; // Celsius
|
||||||
const float TIME_TO_HOT = 150.0; // Seconds
|
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_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 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
|
const float BAD_ERROR_TEMPERATURE = 2000.0; // must exceed BAD_HIGH_TEMPERATURE
|
||||||
|
|
||||||
|
|
21
ExternalDrivers.h
Normal file
21
ExternalDrivers.h
Normal file
|
@ -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_ */
|
|
@ -65,12 +65,14 @@ bool GCodeBuffer::Put(char c)
|
||||||
// Deal with line numbers and checksums
|
// Deal with line numbers and checksums
|
||||||
if (Seen('*'))
|
if (Seen('*'))
|
||||||
{
|
{
|
||||||
int csSent = GetIValue();
|
const int csSent = GetIValue();
|
||||||
int csHere = CheckSum();
|
const int csHere = CheckSum();
|
||||||
Seen('N');
|
|
||||||
if (csSent != csHere)
|
if (csSent != csHere)
|
||||||
|
{
|
||||||
|
if (Seen('N'))
|
||||||
{
|
{
|
||||||
snprintf(gcodeBuffer, GCODE_LENGTH, "M998 P%d", GetIValue());
|
snprintf(gcodeBuffer, GCODE_LENGTH, "M998 P%d", GetIValue());
|
||||||
|
}
|
||||||
Init();
|
Init();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
106
GCodes.cpp
106
GCodes.cpp
|
@ -3550,8 +3550,19 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
|
||||||
}
|
}
|
||||||
break;
|
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
|
case 144: // Set bed to standby
|
||||||
#if BED_HEATER != -1
|
#if BED_HEATER >= 0
|
||||||
reprap.GetHeat()->Standby(BED_HEATER);
|
reprap.GetHeat()->Standby(BED_HEATER);
|
||||||
#else
|
#else
|
||||||
reply.copy("Hot bed is not present!");
|
reply.copy("Hot bed is not present!");
|
||||||
|
@ -3559,14 +3570,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case 160: //number of mixing filament drives TODO: With tools defined, is this needed?
|
case 190: // Set bed temperature and wait
|
||||||
// if(gb->Seen('S'))
|
|
||||||
// {
|
|
||||||
// platform->SetMixingDrives(gb->GetIValue());
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
|
|
||||||
case 190: // Deprecated...
|
|
||||||
if (!AllMovesAreFinishedAndMoveBufferIsLoaded()) // tell Move not to wait for more moves
|
if (!AllMovesAreFinishedAndMoveBufferIsLoaded()) // tell Move not to wait for more moves
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -3818,9 +3822,75 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
|
||||||
SetHeaterParameters(gb, reply);
|
SetHeaterParameters(gb, reply);
|
||||||
break;
|
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
|
case 400: // Wait for current moves to finish
|
||||||
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
|
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 404: // Filament width and nozzle diameter
|
case 404: // Filament width and nozzle diameter
|
||||||
|
@ -4610,7 +4680,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 579: // Scale Cartesian axes (for Delta configurations)
|
case 579: // Scale Cartesian axes (mostly for Delta configurations)
|
||||||
{
|
{
|
||||||
bool seen = false;
|
bool seen = false;
|
||||||
for(size_t axis = 0; axis < AXES; axis++)
|
for(size_t axis = 0; axis < AXES; axis++)
|
||||||
|
@ -4820,6 +4890,10 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 906: // Set/report Motor currents
|
case 906: // Set/report Motor currents
|
||||||
|
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
bool seen = false;
|
bool seen = false;
|
||||||
for (size_t axis = 0; axis < AXES; axis++)
|
for (size_t axis = 0; axis < AXES; axis++)
|
||||||
|
@ -4856,13 +4930,17 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
|
||||||
|
|
||||||
if (!seen)
|
if (!seen)
|
||||||
{
|
{
|
||||||
reply.printf("Axis currents (mA) - X:%d, Y:%d, Z:%d, E:", (int) platform->MotorCurrent(X_AXIS),
|
reply.copy("Axis currents (mA) - ");
|
||||||
(int) platform->MotorCurrent(Y_AXIS), (int) platform->MotorCurrent(Z_AXIS));
|
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++)
|
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;
|
break;
|
||||||
|
|
84
Heat.cpp
84
Heat.cpp
|
@ -163,8 +163,8 @@ void PID::Spin()
|
||||||
|
|
||||||
// Always know our temperature, regardless of whether we have been switched on or not
|
// 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
|
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
|
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, 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
|
// 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
|
// We are switched on. Check for faults. Temperature silly-low or silly-high mean open-circuit
|
||||||
// or shorted thermistor respectively.
|
// 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)))
|
if (platform->DoThermistorAdc(heater) || !(Platform::TempErrorPermanent(err)))
|
||||||
{
|
{
|
||||||
|
@ -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);
|
// 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
|
float PID::GetAveragePWM() const
|
||||||
{
|
{
|
||||||
return averagePWM * invHeatPwmAverageCount;
|
return averagePWM * invHeatPwmAverageCount;
|
||||||
|
|
69
Heat.h
69
Heat.h
|
@ -137,33 +137,11 @@ inline bool PID::Active() const
|
||||||
return active;
|
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
|
inline float PID::GetActiveTemperature() const
|
||||||
{
|
{
|
||||||
return activeTemperature;
|
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
|
inline float PID::GetStandbyTemperature() const
|
||||||
{
|
{
|
||||||
return standbyTemperature;
|
return standbyTemperature;
|
||||||
|
@ -174,58 +152,11 @@ inline float PID::GetTemperature() const
|
||||||
return temperature;
|
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
|
inline bool PID::FaultOccurred() const
|
||||||
{
|
{
|
||||||
return temperatureFault;
|
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
|
inline bool PID::SwitchedOff() const
|
||||||
{
|
{
|
||||||
return switchedOff;
|
return switchedOff;
|
||||||
|
|
|
@ -85,7 +85,7 @@ extern void pinModeNonDue(uint32_t ulPin, uint32_t ulMode, uint32_t debounceCuto
|
||||||
return;
|
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 (pinDesc.ulPinType == PIO_NOT_A_PIN)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -153,7 +153,7 @@ extern void digitalWriteNonDue(uint32_t ulPin, uint32_t ulVal)
|
||||||
return;
|
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 (pinDesc.ulPinType != PIO_NOT_A_PIN)
|
||||||
{
|
{
|
||||||
if (ulVal) // we make use of the fact that LOW is zero and HIGH is nonzero
|
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;
|
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)
|
if (pinDesc.ulPinType == PIO_NOT_A_PIN)
|
||||||
{
|
{
|
||||||
return LOW ;
|
return LOW ;
|
||||||
|
@ -191,7 +191,7 @@ extern int digitalReadNonDue( uint32_t ulPin )
|
||||||
// Build a short-form pin descriptor for a IO pin
|
// Build a short-form pin descriptor for a IO pin
|
||||||
OutputPin::OutputPin(unsigned int 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;
|
pPort = pinDesc.pPort;
|
||||||
ulPin = pinDesc.ulPin;
|
ulPin = pinDesc.ulPin;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ void analogWriteNonDue(uint32_t ulPin, uint32_t ulValue, uint16_t freq)
|
||||||
ulValue = 255;
|
ulValue = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PinDescription& pinDesc = (ulPin >= X0) ? nonDuePinDescription[ulPin - X0] : g_APinDescription[ulPin];
|
const PinDescription& pinDesc = GetPinDescription(ulPin);
|
||||||
uint32_t attr = pinDesc.ulPinAttribute;
|
uint32_t attr = pinDesc.ulPinAttribute;
|
||||||
if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
|
if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,18 +84,22 @@ public:
|
||||||
void SetLow() const { pPort->PIO_CODR = ulPin; }
|
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 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);
|
inline const PinDescription& GetPinDescription(uint32_t ulPin)
|
||||||
extern int digitalReadNonDue(uint32_t ulPin);
|
{
|
||||||
extern OutputPin getPioPin(uint32_t ulPin);
|
return (ulPin >= X0) ? nonDuePinDescription[ulPin - X0] : g_APinDescription[ulPin];
|
||||||
extern void analogWriteNonDue(uint32_t ulPin, uint32_t ulValue, uint16_t freq);
|
}
|
||||||
extern void analogOutputNonDue();
|
|
||||||
extern void hsmciPinsinit();
|
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 ethPinsInit();
|
void digitalWriteNonDue(uint32_t ulPin, uint32_t ulVal);
|
||||||
extern adc_channel_num_t PinToAdcChannel(int pin); // convert an analog pin number to an ADC channel
|
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 */
|
#endif /* SAM_NON_DUE_PIN_H */
|
||||||
|
|
||||||
|
|
165
Platform.cpp
165
Platform.cpp
|
@ -22,6 +22,10 @@
|
||||||
#include "RepRapFirmware.h"
|
#include "RepRapFirmware.h"
|
||||||
#include "DueFlashStorage.h"
|
#include "DueFlashStorage.h"
|
||||||
|
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
#include "ExternalDrivers.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern char _end;
|
extern char _end;
|
||||||
extern "C" char *sbrk(int i);
|
extern "C" char *sbrk(int i);
|
||||||
|
|
||||||
|
@ -109,8 +113,7 @@ bool PidParameters::operator==(const PidParameters& other) const
|
||||||
|
|
||||||
Platform::Platform() :
|
Platform::Platform() :
|
||||||
autoSaveEnabled(false), board(DEFAULT_BOARD_TYPE), active(false), errorCodeBits(0),
|
autoSaveEnabled(false), board(DEFAULT_BOARD_TYPE), active(false), errorCodeBits(0),
|
||||||
fileStructureInitialised(false), tickState(0), debugCode(0),
|
fileStructureInitialised(false), tickState(0), debugCode(0)
|
||||||
messageString(messageStringBuffer, ARRAY_SIZE(messageStringBuffer))
|
|
||||||
{
|
{
|
||||||
// Output
|
// Output
|
||||||
auxOutput = new OutputStack();
|
auxOutput = new OutputStack();
|
||||||
|
@ -148,7 +151,9 @@ void Platform::Init()
|
||||||
|
|
||||||
SERIAL_MAIN_DEVICE.begin(baudRates[0]);
|
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
|
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]);
|
SERIAL_AUX2_DEVICE.begin(baudRates[2]);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reconfigure the ADC to avoid crosstalk between channels (especially on Duet 0.8.5)
|
// 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
|
adc_init(ADC, SystemCoreClock, ADC_FREQ_MIN, ADC_STARTUP_FAST); // reduce clock rate
|
||||||
|
@ -240,7 +245,11 @@ void Platform::Init()
|
||||||
{
|
{
|
||||||
pinModeNonDue(directionPins[drive], OUTPUT);
|
pinModeNonDue(directionPins[drive], OUTPUT);
|
||||||
}
|
}
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
if (drive < FIRST_EXTERNAL_DRIVE && enablePins[drive] >= 0)
|
||||||
|
#else
|
||||||
if (enablePins[drive] >= 0)
|
if (enablePins[drive] >= 0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
pinModeNonDue(enablePins[drive], OUTPUT);
|
pinModeNonDue(enablePins[drive], OUTPUT);
|
||||||
}
|
}
|
||||||
|
@ -261,6 +270,10 @@ void Platform::Init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
ExternalDrivers::Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
extrusionAncilliaryPWM = 0.0;
|
extrusionAncilliaryPWM = 0.0;
|
||||||
|
|
||||||
// HEATERS - Bed is assumed to be index 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
|
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
|
SetThermistorNumber(heater, heater); // map the thermistor straight through
|
||||||
thermistorFilters[heater].Init(analogRead(tempSensePins[heater]));
|
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();
|
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
|
// Specify which thermistor channel a particular heater uses
|
||||||
void Platform::SetThermistorNumber(size_t heater, size_t thermistor)
|
void Platform::SetThermistorNumber(size_t heater, size_t thermistor)
|
||||||
//pre(heater < HEATERS && thermistor < HEATERS)
|
//pre(heater < HEATERS && thermistor < HEATERS)
|
||||||
|
@ -781,6 +802,7 @@ void Platform::Spin()
|
||||||
OutputBuffer *aux2OutputBuffer = aux2Output->GetFirstItem();
|
OutputBuffer *aux2OutputBuffer = aux2Output->GetFirstItem();
|
||||||
if (aux2OutputBuffer != nullptr)
|
if (aux2OutputBuffer != nullptr)
|
||||||
{
|
{
|
||||||
|
#ifdef SERIAL_AUX2_DEVICE
|
||||||
size_t bytesToWrite = min<size_t>(SERIAL_AUX2_DEVICE.canWrite(), aux2OutputBuffer->BytesLeft());
|
size_t bytesToWrite = min<size_t>(SERIAL_AUX2_DEVICE.canWrite(), aux2OutputBuffer->BytesLeft());
|
||||||
if (bytesToWrite > 0)
|
if (bytesToWrite > 0)
|
||||||
{
|
{
|
||||||
|
@ -792,6 +814,9 @@ void Platform::Spin()
|
||||||
aux2OutputBuffer = OutputBuffer::Release(aux2OutputBuffer);
|
aux2OutputBuffer = OutputBuffer::Release(aux2OutputBuffer);
|
||||||
aux2Output->SetFirstItem(aux2OutputBuffer);
|
aux2Output->SetFirstItem(aux2OutputBuffer);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
aux2OutputBuffer = OutputBuffer::Release(aux2OutputBuffer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write non-blocking data to the USB line
|
// Write non-blocking data to the USB line
|
||||||
|
@ -868,7 +893,11 @@ void Platform::SoftwareReset(uint16_t reason)
|
||||||
{
|
{
|
||||||
reason |= (uint16_t)SoftwareResetReason::inLwipSpin;
|
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
|
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.magic = SoftwareResetData::magicValue;
|
||||||
temp.resetReason = reason;
|
temp.resetReason = reason;
|
||||||
GetStackUsage(NULL, NULL, &temp.neverUsedRam);
|
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
|
// Save diagnostics data to Flash and reset the software
|
||||||
DueFlashStorage::write(SoftwareResetData::nvAddress, &temp, sizeof(SoftwareResetData));
|
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, "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]);
|
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
|
else
|
||||||
{
|
{
|
||||||
// thermistor short circuit, return a high temperature
|
// thermistor short circuit, return a high temperature
|
||||||
if (err) *err = TempError::errShort;
|
if (err)
|
||||||
|
{
|
||||||
|
*err = TempError::errShort;
|
||||||
|
}
|
||||||
return BAD_ERROR_TEMPERATURE;
|
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::errShortVcc : return "sensor circuit is shorted to the voltage rail";
|
||||||
case TempError::errShortGnd : return "sensor circuit is shorted to ground";
|
case TempError::errShortGnd : return "sensor circuit is shorted to ground";
|
||||||
case TempError::errOpen : return "sensor circuit is open/disconnected";
|
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::errTimeout : return "communication error whilst reading sensor; read took too long";
|
||||||
case TempError::errIO: return "communication error whilst reading sensor; check sensor connections";
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the heater PID parameters or thermistor resistance etc.
|
||||||
void Platform::SetPidParameters(size_t heater, const PidParameters& params)
|
void Platform::SetPidParameters(size_t heater, const PidParameters& params)
|
||||||
{
|
{
|
||||||
if (heater < HEATERS && params != nvData.pidParams[heater])
|
if (heater < HEATERS && params != nvData.pidParams[heater])
|
||||||
|
@ -1247,6 +1268,7 @@ void Platform::SetPidParameters(size_t heater, const PidParameters& params)
|
||||||
{
|
{
|
||||||
WriteNvData();
|
WriteNvData();
|
||||||
}
|
}
|
||||||
|
SetTemperatureLimit(temperatureLimit); // recalculate the thermistor resistance at max allowed temperature for the tick ISR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const PidParameters& Platform::GetPidParameters(size_t heater) const
|
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
|
UpdateMotorCurrent(driver); // the current may have been reduced by the idle timeout
|
||||||
|
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
if (drive >= FIRST_EXTERNAL_DRIVE)
|
||||||
|
{
|
||||||
|
ExternalDrivers::EnableDrive(driver - FIRST_EXTERNAL_DRIVE, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
const int pin = enablePins[driver];
|
const int pin = enablePins[driver];
|
||||||
if (pin >= 0)
|
if (pin >= 0)
|
||||||
{
|
{
|
||||||
digitalWriteNonDue(pin, enableValues[driver]);
|
digitalWriteNonDue(pin, enableValues[driver]);
|
||||||
}
|
}
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1344,12 +1377,23 @@ void Platform::DisableDrive(size_t drive)
|
||||||
if (drive < DRIVES)
|
if (drive < DRIVES)
|
||||||
{
|
{
|
||||||
const size_t driver = driverNumbers[drive];
|
const size_t driver = driverNumbers[drive];
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
if (drive >= FIRST_EXTERNAL_DRIVE)
|
||||||
|
{
|
||||||
|
ExternalDrivers::EnableDrive(driver - FIRST_EXTERNAL_DRIVE, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
const int pin = enablePins[driver];
|
const int pin = enablePins[driver];
|
||||||
if (pin >= 0)
|
if (pin >= 0)
|
||||||
{
|
{
|
||||||
digitalWriteNonDue(pin, !enableValues[driver]);
|
digitalWriteNonDue(pin, !enableValues[driver]);
|
||||||
}
|
}
|
||||||
driveState[drive] = DriveStatus::disabled;
|
driveState[drive] = DriveStatus::disabled;
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1387,9 +1431,17 @@ void Platform::UpdateMotorCurrent(size_t drive)
|
||||||
{
|
{
|
||||||
current *= idleCurrentFactor;
|
current *= idleCurrentFactor;
|
||||||
}
|
}
|
||||||
|
const size_t driver = driverNumbers[drive];
|
||||||
|
#ifdef EXTERNAL_DRIVERS
|
||||||
|
if (driver >= FIRST_EXTERNAL_DRIVE)
|
||||||
|
{
|
||||||
|
ExternalDrivers::SetCurrent(driver - FIRST_EXTERNAL_DRIVE, current);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
unsigned short pot = (unsigned short)((0.256*current*8.0*senseResistor + maxStepperDigipotVoltage/2)/maxStepperDigipotVoltage);
|
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);
|
unsigned short dac = (unsigned short)((0.256*current*8.0*senseResistor + maxStepperDACVoltage/2)/maxStepperDACVoltage);
|
||||||
const size_t driver = driverNumbers[drive];
|
|
||||||
if (driver < 4)
|
if (driver < 4)
|
||||||
{
|
{
|
||||||
mcpDuet.setNonVolatileWiper(potWipes[driver], pot);
|
mcpDuet.setNonVolatileWiper(potWipes[driver], pot);
|
||||||
|
@ -1416,6 +1468,9 @@ void Platform::UpdateMotorCurrent(size_t drive)
|
||||||
mcpExpansion.setVolatileWiper(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
|
// Set the physical drive (i.e. axis or extruder) number used by this driver
|
||||||
void Platform::SetPhysicalDrive(size_t driverNumber, int8_t physicalDrive)
|
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)
|
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
|
// 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)
|
if (NUM_FANS > 1)
|
||||||
|
@ -1711,6 +1808,7 @@ void Platform::Message(MessageType type, const char *message)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUX2_MESSAGE:
|
case AUX2_MESSAGE:
|
||||||
|
#ifdef SERIAL_AUX2_DEVICE
|
||||||
// Message that is to be sent to the second auxiliary device (blocking)
|
// Message that is to be sent to the second auxiliary device (blocking)
|
||||||
if (!aux2Output->IsEmpty())
|
if (!aux2Output->IsEmpty())
|
||||||
{
|
{
|
||||||
|
@ -1723,6 +1821,7 @@ void Platform::Message(MessageType type, const char *message)
|
||||||
SERIAL_AUX2_DEVICE.write(message);
|
SERIAL_AUX2_DEVICE.write(message);
|
||||||
SERIAL_AUX2_DEVICE.flush();
|
SERIAL_AUX2_DEVICE.flush();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DISPLAY_MESSAGE:
|
case DISPLAY_MESSAGE:
|
||||||
|
@ -1965,10 +2064,12 @@ void Platform::ResetChannel(size_t chan)
|
||||||
SERIAL_AUX_DEVICE.end();
|
SERIAL_AUX_DEVICE.end();
|
||||||
SERIAL_AUX_DEVICE.begin(baudRates[1]);
|
SERIAL_AUX_DEVICE.begin(baudRates[1]);
|
||||||
break;
|
break;
|
||||||
|
#ifdef SERIAL_AUX2_DEVICE
|
||||||
case 2:
|
case 2:
|
||||||
SERIAL_AUX2_DEVICE.end();
|
SERIAL_AUX2_DEVICE.end();
|
||||||
SERIAL_AUX2_DEVICE.begin(baudRates[2]);
|
SERIAL_AUX2_DEVICE.begin(baudRates[2]);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
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.
|
// 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.
|
// 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.
|
// 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);
|
pinModeNonDue(Dac0DigitalPin, INPUT_PULLUP);
|
||||||
board = (digitalReadNonDue(Dac0DigitalPin)) ? BoardType::Duet_06 : BoardType::Duet_085;
|
board = (digitalReadNonDue(Dac0DigitalPin)) ? BoardType::Duet_06 : BoardType::Duet_085;
|
||||||
pinModeNonDue(Dac0DigitalPin, INPUT); // turn pullup off
|
pinModeNonDue(Dac0DigitalPin, INPUT); // turn pullup off
|
||||||
|
@ -2088,7 +2189,11 @@ bool Platform::GCodeAvailable(const SerialSource source) const
|
||||||
return SERIAL_AUX_DEVICE.available() > 0;
|
return SERIAL_AUX_DEVICE.available() > 0;
|
||||||
|
|
||||||
case SerialSource::AUX2:
|
case SerialSource::AUX2:
|
||||||
|
#ifdef SERIAL_AUX2_DEVICE
|
||||||
return SERIAL_AUX2_DEVICE.available() > 0;
|
return SERIAL_AUX2_DEVICE.available() > 0;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -2105,7 +2210,11 @@ char Platform::ReadFromSource(const SerialSource source)
|
||||||
return static_cast<char>(SERIAL_AUX_DEVICE.read());
|
return static_cast<char>(SERIAL_AUX_DEVICE.read());
|
||||||
|
|
||||||
case SerialSource::AUX2:
|
case SerialSource::AUX2:
|
||||||
|
#ifdef SERIAL_AUX2_DEVICE
|
||||||
return static_cast<char>(SERIAL_AUX2_DEVICE.read());
|
return static_cast<char>(SERIAL_AUX2_DEVICE.read());
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2180,7 +2289,7 @@ void Platform::Tick()
|
||||||
// averaging. As such, the temperature reading is taken directly by Platform::GetTemperature() and
|
// 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
|
// 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().
|
// 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);
|
StartAdcConversion(zProbeAdcChannel);
|
||||||
if ((millis() - reprap.GetHeat()->GetLastSampleTime(currentHeater)) > maxPidSpinDelay)
|
if ((millis() - reprap.GetHeat()->GetLastSampleTime(currentHeater)) > maxPidSpinDelay)
|
||||||
{
|
{
|
||||||
|
|
19
Platform.h
19
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
|
enum class BoardType : uint8_t
|
||||||
{
|
{
|
||||||
Auto = 0,
|
Auto = 0,
|
||||||
|
@ -423,7 +417,7 @@ public:
|
||||||
enum class DriveStatus : uint8_t { disabled, idle, enabled };
|
enum class DriveStatus : uint8_t { disabled, idle, enabled };
|
||||||
|
|
||||||
// Error results generated by GetTemperature()
|
// 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();
|
Platform();
|
||||||
|
|
||||||
|
@ -515,6 +509,8 @@ public:
|
||||||
float MotorCurrent(size_t drive) const;
|
float MotorCurrent(size_t drive) const;
|
||||||
void SetIdleCurrentFactor(float f);
|
void SetIdleCurrentFactor(float f);
|
||||||
float GetIdleCurrentFactor() const { return idleCurrentFactor; }
|
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;
|
float DriveStepsPerUnit(size_t drive) const;
|
||||||
const float *GetDriveStepsPerUnit() const { return driveStepsPerUnit; }
|
const float *GetDriveStepsPerUnit() const { return driveStepsPerUnit; }
|
||||||
void SetDriveStepsPerUnit(size_t drive, float value);
|
void SetDriveStepsPerUnit(size_t drive, float value);
|
||||||
|
@ -574,7 +570,8 @@ public:
|
||||||
void SetThermistorNumber(size_t heater, size_t thermistor);
|
void SetThermistorNumber(size_t heater, size_t thermistor);
|
||||||
int GetThermistorNumber(size_t heater) const;
|
int GetThermistorNumber(size_t heater) const;
|
||||||
bool DoThermistorAdc(uint8_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 const char* TempErrorStr(TempError err);
|
||||||
static bool TempErrorPermanent(TempError err);
|
static bool TempErrorPermanent(TempError err);
|
||||||
|
|
||||||
|
@ -638,7 +635,6 @@ private:
|
||||||
uint16_t magic;
|
uint16_t magic;
|
||||||
uint16_t resetReason; // this records why we did a software reset, for diagnostic purposes
|
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
|
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
|
struct FlashData
|
||||||
|
@ -759,11 +755,13 @@ private:
|
||||||
|
|
||||||
Pin tempSensePins[HEATERS];
|
Pin tempSensePins[HEATERS];
|
||||||
Pin heatOnPins[HEATERS];
|
Pin heatOnPins[HEATERS];
|
||||||
|
MAX31855 Max31855Devices[MAX31855_DEVICES];
|
||||||
Pin max31855CsPins[MAX31855_DEVICES];
|
Pin max31855CsPins[MAX31855_DEVICES];
|
||||||
float heatSampleTime;
|
float heatSampleTime;
|
||||||
float standbyTemperatures[HEATERS];
|
float standbyTemperatures[HEATERS];
|
||||||
float activeTemperatures[HEATERS];
|
float activeTemperatures[HEATERS];
|
||||||
float timeToHot;
|
float timeToHot;
|
||||||
|
float temperatureLimit;
|
||||||
|
|
||||||
// Fans
|
// Fans
|
||||||
|
|
||||||
|
@ -836,9 +834,6 @@ private:
|
||||||
static uint16_t GetAdcReading(adc_channel_num_t chan);
|
static uint16_t GetAdcReading(adc_channel_num_t chan);
|
||||||
static void StartAdcConversion(adc_channel_num_t chan);
|
static void StartAdcConversion(adc_channel_num_t chan);
|
||||||
|
|
||||||
char messageStringBuffer[messageStringLength];
|
|
||||||
StringRef messageString;
|
|
||||||
|
|
||||||
// Hotend configuration
|
// Hotend configuration
|
||||||
float filamentWidth;
|
float filamentWidth;
|
||||||
float nozzleDiameter;
|
float nozzleDiameter;
|
||||||
|
|
|
@ -723,9 +723,11 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const
|
||||||
const float fractionPrinted = gCodes->FractionOfFilePrinted();
|
const float fractionPrinted = gCodes->FractionOfFilePrinted();
|
||||||
if (numLayerSamples < 2 || !printingFileParsed || printingFileInfo.objectHeight == 0.0)
|
if (numLayerSamples < 2 || !printingFileParsed || printingFileInfo.objectHeight == 0.0)
|
||||||
{
|
{
|
||||||
return (fractionPrinted < 0.01)
|
if (fractionPrinted < 0.01)
|
||||||
? 0.0
|
{
|
||||||
: realPrintDuration * (1.0 / fractionPrinted) - realPrintDuration;
|
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.
|
// Work out how much progress we made in the layers we have data for, and how long it took.
|
||||||
|
@ -736,10 +738,12 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const
|
||||||
duration += layerDurations[layer];
|
duration += layerDurations[layer];
|
||||||
}
|
}
|
||||||
const float fractionPrintedInLayers = fileProgressPerLayer[numLayerSamples - 1] - fileProgressPerLayer[0];
|
const float fractionPrintedInLayers = fileProgressPerLayer[numLayerSamples - 1] - fileProgressPerLayer[0];
|
||||||
return (fractionPrintedInLayers < 0.01)
|
if (fractionPrintedInLayers >= 0.01)
|
||||||
? 0.0
|
{
|
||||||
: duration * (1.0 - fractionPrinted)/fractionPrintedInLayers;
|
return duration * (1.0 - fractionPrinted)/fractionPrintedInLayers;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case filamentBased:
|
case filamentBased:
|
||||||
{
|
{
|
||||||
|
@ -750,7 +754,7 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return 0.0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum up the filament usage and the filament needed
|
// Sum up the filament usage and the filament needed
|
||||||
|
@ -770,22 +774,35 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const
|
||||||
}
|
}
|
||||||
if (extrRawTotal >= totalFilamentNeeded)
|
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;
|
float filamentRate;
|
||||||
if (numLayerSamples)
|
if (numLayerSamples != 0)
|
||||||
{
|
{
|
||||||
filamentRate = 0.0;
|
filamentRate = 0.0;
|
||||||
|
size_t numSamples = 0;
|
||||||
for (size_t i = 0; i < numLayerSamples; i++)
|
for (size_t i = 0; i < numLayerSamples; i++)
|
||||||
|
{
|
||||||
|
if (layerDurations[i] > 0.0)
|
||||||
{
|
{
|
||||||
filamentRate += filamentUsagePerLayer[i] / layerDurations[i];
|
filamentRate += filamentUsagePerLayer[i] / layerDurations[i];
|
||||||
|
++numSamples;
|
||||||
}
|
}
|
||||||
filamentRate /= numLayerSamples;
|
}
|
||||||
|
if (numSamples == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
filamentRate /= numSamples;
|
||||||
|
}
|
||||||
|
else if (firstLayerDuration > 0.0)
|
||||||
|
{
|
||||||
|
filamentRate = firstLayerFilament / firstLayerDuration;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
filamentRate = firstLayerFilament / firstLayerDuration;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (totalFilamentNeeded - extrRawTotal) / filamentRate;
|
return (totalFilamentNeeded - extrRawTotal) / filamentRate;
|
||||||
|
|
BIN
Release/RepRapFirmware-1.09sbeta4-dc42.bin
Normal file
BIN
Release/RepRapFirmware-1.09sbeta4-dc42.bin
Normal file
Binary file not shown.
27
Reprap.cpp
27
Reprap.cpp
|
@ -163,7 +163,7 @@ void RepRap::Spin()
|
||||||
{
|
{
|
||||||
if (t->DisplayColdExtrudeWarning() && ToolWarningsAllowed())
|
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,19 +1341,28 @@ void RepRap::SetName(const char* nm)
|
||||||
network->SetHostname(myName);
|
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.
|
// For each disallowed one, log an error to report later and return a bit in the bitmap.
|
||||||
// This may be called by an ISR!
|
// This may be called by an ISR!
|
||||||
unsigned int RepRap::GetProhibitedExtruderMovements(unsigned int extrusions, unsigned int retractions)
|
unsigned int RepRap::GetProhibitedExtruderMovements(unsigned int extrusions, unsigned int retractions)
|
||||||
{
|
{
|
||||||
unsigned int result = 0;
|
if (GetHeat()->ColdExtrude())
|
||||||
Tool *tool = toolList;
|
|
||||||
while (tool != nullptr)
|
|
||||||
{
|
{
|
||||||
|
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++)
|
for (size_t driveNum = 0; driveNum < tool->DriveCount(); driveNum++)
|
||||||
{
|
{
|
||||||
const int extruderDrive = tool->Drive(driveNum);
|
const unsigned int extruderDrive = (unsigned int)(tool->Drive(driveNum));
|
||||||
unsigned int mask = 1 << extruderDrive;
|
const unsigned int mask = 1 << extruderDrive;
|
||||||
if (extrusions & mask)
|
if (extrusions & mask)
|
||||||
{
|
{
|
||||||
if (!tool->ToolCanDrive(true))
|
if (!tool->ToolCanDrive(true))
|
||||||
|
@ -1361,7 +1370,7 @@ unsigned int RepRap::GetProhibitedExtruderMovements(unsigned int extrusions, uns
|
||||||
result |= mask;
|
result |= mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (retractions & (1 << extruderDrive))
|
else if (retractions & mask)
|
||||||
{
|
{
|
||||||
if (!tool->ToolCanDrive(false))
|
if (!tool->ToolCanDrive(false))
|
||||||
{
|
{
|
||||||
|
@ -1370,8 +1379,6 @@ unsigned int RepRap::GetProhibitedExtruderMovements(unsigned int extrusions, uns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tool = tool->Next();
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
Tool.cpp
23
Tool.cpp
|
@ -31,13 +31,15 @@ Tool * Tool::freelist = nullptr;
|
||||||
{
|
{
|
||||||
if (dCount > DRIVES - AXES)
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hCount > HEATERS)
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +122,7 @@ void Tool::Print(StringRef& reply)
|
||||||
{
|
{
|
||||||
comma = ';';
|
comma = ';';
|
||||||
}
|
}
|
||||||
reply.catf("%d (%.1f/%.1f)%c", heaters[heater],
|
reply.catf("%d (%.1f/%.1f)%c", heaters[heater], activeTemperatures[heater], standbyTemperatures[heater], comma);
|
||||||
activeTemperatures[heater], standbyTemperatures[heater], comma);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.catf(" status: %s", active ? "selected" : "standby");
|
reply.catf(" status: %s", active ? "selected" : "standby");
|
||||||
|
@ -131,7 +132,8 @@ float Tool::MaxFeedrate() const
|
||||||
{
|
{
|
||||||
if (driveCount <= 0)
|
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;
|
return 1.0;
|
||||||
}
|
}
|
||||||
float result = 0.0;
|
float result = 0.0;
|
||||||
|
@ -269,12 +271,12 @@ void Tool::SetVariables(const float* standby, const float* active)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (active[heater] < BAD_HIGH_TEMPERATURE)
|
if (active[heater] < reprap.GetPlatform()->GetTemperatureLimit())
|
||||||
{
|
{
|
||||||
activeTemperatures[heater] = active[heater];
|
activeTemperatures[heater] = active[heater];
|
||||||
reprap.GetHeat()->SetActiveTemperature(heaters[heater], activeTemperatures[heater]);
|
reprap.GetHeat()->SetActiveTemperature(heaters[heater], activeTemperatures[heater]);
|
||||||
}
|
}
|
||||||
if (standby[heater] < BAD_HIGH_TEMPERATURE)
|
if (standby[heater] < reprap.GetPlatform()->GetTemperatureLimit())
|
||||||
{
|
{
|
||||||
standbyTemperatures[heater] = standby[heater];
|
standbyTemperatures[heater] = standby[heater];
|
||||||
reprap.GetHeat()->SetStandbyTemperature(heaters[heater], standbyTemperatures[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
|
// May be called from ISR
|
||||||
bool Tool::ToolCanDrive(bool extrude)
|
bool Tool::ToolCanDrive(bool extrude)
|
||||||
{
|
{
|
||||||
if (heaterFault)
|
if (!heaterFault && AllHeatersAtHighTemperature(extrude))
|
||||||
return false;
|
{
|
||||||
|
|
||||||
if (reprap.GetHeat()->ColdExtrude() || AllHeatersAtHighTemperature(extrude))
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
displayColdExtrudeWarning = true;
|
displayColdExtrudeWarning = true;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -96,8 +96,8 @@
|
||||||
|
|
||||||
//***************************************************************************************************
|
//***************************************************************************************************
|
||||||
|
|
||||||
static const char* overflowResponse = "overflow";
|
const char* overflowResponse = "overflow";
|
||||||
static const char* badEscapeResponse = "bad escape";
|
const char* badEscapeResponse = "bad escape";
|
||||||
|
|
||||||
|
|
||||||
//********************************************************************************************
|
//********************************************************************************************
|
||||||
|
|
Reference in a new issue