diff options
Diffstat (limited to 'src/Platform.cpp')
-rw-r--r-- | src/Platform.cpp | 318 |
1 files changed, 86 insertions, 232 deletions
diff --git a/src/Platform.cpp b/src/Platform.cpp index ec31cae7..66eaf063 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -415,7 +415,7 @@ void Platform::Init() directions[drive] = true; // drive moves forwards by default // Map axes and extruders straight through - if (drive < MAX_AXES) + if (drive < MaxAxes) { axisDrivers[drive].numDrivers = 1; axisDrivers[drive].driverNumbers[0] = (uint8_t)drive; @@ -430,11 +430,6 @@ void Platform::Init() endStopLogicLevel[drive] = true; // assume all endstops use active high logic e.g. normally-closed switch to ground } - if (drive >= MIN_AXES) - { - extruderDrivers[drive - MIN_AXES] = (uint8_t)drive; - SetPressureAdvance(drive - MIN_AXES, 0.0); - } driveDriverBits[drive] = CalcDriverBitmap(drive); // Set up the control pins and endstops @@ -453,6 +448,12 @@ void Platform::Init() slowDriverStepPulseClocks = 0; // no extended driver timing configured yet slowDrivers = 0; // assume no drivers need extended step pulse timing + for (size_t extr = 0; extr < MaxExtruders; ++extr) + { + extruderDrivers[extr] = (uint8_t)(extr + MinAxes); // set up default extruder drive mapping + SetPressureAdvance(extr, 0.0); + } + #ifdef DUET_NG // Test for presence of a DueX2 or DueX5 expansion board and work out how many TMC2660 drivers we have // The SX1509B has an independent power on reset, so give it some time @@ -521,7 +522,7 @@ void Platform::Init() setPullup(SpiTempSensorCsPins[i], true); } - for (size_t heater = 0; heater < HEATERS; heater++) + for (size_t heater = 0; heater < Heaters; heater++) { if (heatOnPins[heater] != NoPin) { @@ -531,13 +532,6 @@ void Platform::Init() pinMode(tempSensePins[heater], AIN); thermistorAdcChannels[heater] = chan; AnalogInEnableChannel(chan, true); - - SetThermistorNumber(heater, heater); // map the thermistor straight through - thermistors[heater].SetParameters( - (heater == DefaultBedHeater) ? BED_R25 : EXT_R25, - (heater == DefaultBedHeater) ? BED_BETA : EXT_BETA, - (heater == DefaultBedHeater) ? BED_SHC : EXT_SHC, - THERMISTOR_SERIES_RS); // initialise the thermistor parameters thermistorFilters[heater].Init(0); } @@ -626,33 +620,6 @@ bool Platform::AnyFileOpen(const FATFS *fs) const return false; } -// Specify which thermistor channel a particular heater uses -void Platform::SetThermistorNumber(size_t heater, size_t thermistor) -{ - heaterTempChannels[heater] = thermistor; - - // Initialize the associated SPI temperature sensor? - if (thermistor >= FirstThermocoupleChannel && thermistor < FirstThermocoupleChannel + MaxSpiTempSensors) - { - SpiTempSensors[thermistor - FirstThermocoupleChannel].InitThermocouple(SpiTempSensorCsPins[thermistor - FirstThermocoupleChannel]); - } - else if (thermistor >= FirstRtdChannel && thermistor < FirstRtdChannel + MaxSpiTempSensors) - { - SpiTempSensors[thermistor - FirstRtdChannel].InitRtd(spiTempSenseCsPins[thermistor - FirstRtdChannel]); - } - else if (thermistor >= FirstLinearAdcChannel && thermistor < FirstLinearAdcChannel + MaxSpiTempSensors) - { - SpiTempSensors[thermistor - FirstRtdChannel].InitLinearAdc(spiTempSenseCsPins[thermistor - FirstLinearAdcChannel]); - } - - reprap.GetHeat().ResetFault(heater); -} - -int Platform::GetThermistorNumber(size_t heater) const -{ - return heaterTempChannels[heater]; -} - void Platform::SetZProbeDefaults() { switchZProbeParameters.Init(0.0); @@ -779,7 +746,7 @@ float Platform::GetZProbeTemperature() if (bedHeater >= 0) { TemperatureError err; - const float temp = GetTemperature(bedHeater, err); + const float temp = reprap.GetHeat().GetTemperature(bedHeater, err); if (err == TemperatureError::success) { return temp; @@ -811,7 +778,7 @@ float Platform::GetZProbeTravelSpeed() const void Platform::SetZProbeType(int pt) { - zProbeType = (pt >= 0 && pt <= 7) ? pt : 0; + zProbeType = (pt >= 0 && pt <= 6) ? pt : 0; InitZProbe(); } @@ -2021,164 +1988,23 @@ void Platform::ClassReport(float &lastTime) } } -//=========================================================================== -//=============================Thermal Settings ============================ -//=========================================================================== - -// See http://en.wikipedia.org/wiki/Thermistor#B_or_.CE.B2_parameter_equation - -// BETA is the B value -// RS is the value of the series resistor in ohms -// R_INF is R0.exp(-BETA/T0), where R0 is the thermistor resistance at T0 (T0 is in kelvin) -// Normally T0 is 298.15K (25 C). - -// If the A->D converter has a range of 0..1023 and the measured voltage is V (between 0 and 1023) -// then the thermistor resistance, R = V.RS/(1024 - V) -// and the temperature, T = BETA/ln(R/R_INF) -// To get degrees celsius (instead of kelvin) add -273.15 to T - -// Result is in degrees celsius - -float Platform::GetTemperature(size_t heater, TemperatureError& err) +#ifdef DUET_NG +// This is called when a fan that monitors driver temperatures is turned on when it was off +void Platform::DriverCoolingFansOn(uint32_t driverChannelsMonitored) { - // Note that at this point we're actually getting an averaged ADC read, not a "raw" temp. For thermistors, - // we're getting an averaged voltage reading which we'll convert to a temperature. - if (IsThermistorChannel(heater)) - { - const volatile ThermistorAveragingFilter& filter = thermistorFilters[heater]; - if (filter.IsValid()) - { - const int32_t averagedReading = filter.GetSum()/(ThermistorAverageReadings >> Thermistor::AdcOversampleBits); - const float temp = thermistors[heater].CalcTemperature(averagedReading); - - if (temp < MinimumConnectedTemperature) - { - // thermistor is disconnected - err = TemperatureError::openCircuit; - return ABS_ZERO; - } - - err = TemperatureError::success; - return temp; - } - - // Filter is not ready yet - err = TemperatureError::busBusy; - return BAD_ERROR_TEMPERATURE; - } - - if (IsThermocoupleChannel(heater)) + if (driverChannelsMonitored & 1) { - // MAX31855 thermocouple chip - float temp; - err = SpiTempSensors[heaterTempChannels[heater] - FirstThermocoupleChannel].GetThermocoupleTemperature(temp); - return (err == TemperatureError::success) ? temp : BAD_ERROR_TEMPERATURE; + onBoardDriversFanStartMillis = millis(); + onBoardDriversFanRunning = true; } - - if (IsRtdChannel(heater)) + if (driverChannelsMonitored & 2) { - // MAX31865 RTD chip - float temp; - err = SpiTempSensors[heaterTempChannels[heater] - FirstRtdChannel].GetRtdTemperature(temp); - return (err == TemperatureError::success) ? temp : BAD_ERROR_TEMPERATURE; + offBoardDriversFanStartMillis = millis(); + offBoardDriversFanRunning = true; } - - if (IsLinearAdcChannel(heater)) - { - // MAX31865 RTD chip - float temp; - err = SpiTempSensors[heaterTempChannels[heater] - FirstRtdChannel].GetLinearAdcTemperature(temp); - return (err == TemperatureError::success) ? temp : BAD_ERROR_TEMPERATURE; - } - - err = TemperatureError::unknownChannel; - return BAD_ERROR_TEMPERATURE; } - -// See if we need to turn on a thermostatically-controlled fan -bool Platform::AnyHeaterHot(uint16_t heaters, float t) -{ - for (size_t h = 0; h < HEATERS; ++h) - { - // Check if this heater is both monitored by this fan and in use - if ( ((1 << h) & heaters) != 0 - && (h < reprap.GetToolHeatersInUse() || (int)h == reprap.GetHeat().GetBedHeater() || (int)h == reprap.GetHeat().GetChamberHeater()) - ) - { - if (reprap.GetHeat().IsTuning(h)) - { - return true; // when turning the PID for a monitored heater, turn the fan on - } - - TemperatureError err; - const float ht = GetTemperature(h, err); - if (err != TemperatureError::success || ht >= t || ht < BAD_LOW_TEMPERATURE) - { - return true; - } - } - } - -#ifndef __RADDS__ - // All boards except RADDS have CPU temperature monitoring - if ((heaters & (1 << HEATERS)) != 0 && AdcReadingToCpuTemperature(cpuTemperatureFilter.GetSum()) >= t) - { - return true; - } #endif -#ifdef DUET_NG - // Duet NG has driver temperature monitoring too - bool turnFanOn = false; - - if ((heaters & (1 << (HEATERS + 1))) != 0) - { - const uint16_t onBoardDriversMask = (1u << 5) - 1; - const float onBoardDriversTemperature = ((temperatureShutdownDrivers & onBoardDriversMask) != 0) ? 150.0 - : ((temperatureWarningDrivers & onBoardDriversMask) != 0) ? 100.0 - : 0.0; - if (onBoardDriversTemperature >= t) - { - if (!onBoardDriversFanRunning) - { - onBoardDriversFanStartMillis = millis(); - } - onBoardDriversFanRunning = true; - turnFanOn = true; - } - else - { - onBoardDriversFanRunning = false; - } - } - - if ((heaters & (1 << (HEATERS + 2))) != 0) - { - const uint16_t offBoardDriversMask = ((1u << 5) - 1) << 5; - const float offBoardDriversTemperature = ((temperatureShutdownDrivers & offBoardDriversMask) != 0) ? 150.0 - : ((temperatureWarningDrivers & offBoardDriversMask) != 0) ? 100.0 - : 0.0; - if (offBoardDriversTemperature >= t) - { - if (!offBoardDriversFanRunning) - { - offBoardDriversFanStartMillis = millis(); - } - offBoardDriversFanRunning = true; - turnFanOn = true; - } - else - { - offBoardDriversFanRunning = false; - } - } - - return turnFanOn; -#else - return false; -#endif -} - // Power is a fraction in [0,1] void Platform::SetHeater(size_t heater, float power) { @@ -2208,7 +2034,7 @@ void Platform::UpdateConfiguredHeaters() } // Check tool heaters - for(size_t heater = 0; heater < HEATERS; heater++) + for(size_t heater = 0; heater < Heaters; heater++) { if (reprap.IsHeaterAssignedToTool(heater)) { @@ -2221,7 +2047,7 @@ EndStopHit Platform::Stopped(size_t drive) const { if (drive < DRIVES && endStopPins[drive] != NoPin) { - if (drive >= reprap.GetGCodes().GetNumAxes()) + if (drive >= reprap.GetGCodes().GetTotalAxes()) { // Endstop not used for an axis, so no configuration data available. // To allow us to see its status in DWC, pretend it is configured as a high-end active high endstop. @@ -2233,7 +2059,7 @@ EndStopHit Platform::Stopped(size_t drive) const else if (endStopType[drive] == EndStopType::noEndStop) { // No homing switch is configured for this axis, so see if we should use the Z probe - if (zProbeType > 0 && drive < reprap.GetGCodes().GetNumAxes() && (zProbeAxes & (1 << drive)) != 0) + if (zProbeType > 0 && drive < reprap.GetGCodes().GetVisibleAxes() && (zProbeAxes & (1 << drive)) != 0) { return GetZProbeResult(); // using the Z probe as a low homing stop for this axis, so just get its result } @@ -2293,7 +2119,7 @@ bool Platform::WriteZProbeParameters(FileStore *f) const // This is called from the step ISR as well as other places, so keep it fast void Platform::SetDirection(size_t drive, bool direction) { - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); if (drive < numAxes) { for (size_t i = 0; i < axisDrivers[drive].numDrivers; ++i) @@ -2354,7 +2180,7 @@ void Platform::DisableDriver(size_t driver) // Enable the drivers for a drive. Must not be called from an ISR, or with interrupts disabled. void Platform::EnableDrive(size_t drive) { - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); if (drive < numAxes) { for (size_t i = 0; i < axisDrivers[drive].numDrivers; ++i) @@ -2371,7 +2197,7 @@ void Platform::EnableDrive(size_t drive) // Disable the drivers for a drive void Platform::DisableDrive(size_t drive) { - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); if (drive < numAxes) { for (size_t i = 0; i < axisDrivers[drive].numDrivers; ++i) @@ -2419,7 +2245,7 @@ void Platform::SetDriverCurrent(size_t driver, float currentOrPercent, bool isPe // Set the current for all drivers on an axis or extruder. Current is in mA. void Platform::SetMotorCurrent(size_t drive, float currentOrPercent, bool isPercent) { - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); if (drive < numAxes) { for (size_t i = 0; i < axisDrivers[drive].numDrivers; ++i) @@ -2515,7 +2341,7 @@ float Platform::GetMotorCurrent(size_t drive, bool isPercent) const { if (drive < DRIVES) { - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); const uint8_t driver = (drive < numAxes) ? axisDrivers[drive].driverNumbers[0] : extruderDrivers[drive - numAxes]; if (driver < DRIVES) { @@ -2566,7 +2392,7 @@ bool Platform::SetDriverMicrostepping(size_t driver, int microsteps, int mode) // Set the microstepping, returning true if successful. All drivers for the same axis must use the same microstepping. bool Platform::SetMicrostepping(size_t drive, int microsteps, int mode) { - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); if (drive < numAxes) { bool ok = true; @@ -2603,7 +2429,7 @@ unsigned int Platform::GetDriverMicrostepping(size_t driver, int mode, bool& int // Get the microstepping for an axis or extruder unsigned int Platform::GetMicrostepping(size_t drive, int mode, bool& interpolation) const { - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); if (drive < numAxes) { return GetDriverMicrostepping(axisDrivers[drive].driverNumbers[0], mode, interpolation); @@ -2634,7 +2460,7 @@ void Platform::SetAxisDriversConfig(size_t drive, const AxisDriversConfig& confi void Platform::SetExtruderDriver(size_t extruder, uint8_t driver) { extruderDrivers[extruder] = driver; - driveDriverBits[extruder + reprap.GetGCodes().GetNumAxes()] = CalcDriverBitmap(driver); + driveDriverBits[extruder + reprap.GetGCodes().GetTotalAxes()] = CalcDriverBitmap(driver); } void Platform::SetDriverStepTiming(size_t driver, float microseconds) @@ -2661,6 +2487,23 @@ float Platform::GetDriverStepTiming(size_t driver) const : 0.0; } +// Set or report the parameters for the specified fan +// If 'mCode' is an M-code used to set parameters for the current kinematics (which should only ever be 106 or 107) +// then search for parameters used to configure the fan. If any are found, perform appropriate actions and return true. +// If errors were discovered while processing parameters, put an appropriate error message in 'reply' and set 'error' to true. +// If no relevant parameters are found, print the existing ones to 'reply' and return false. +bool Platform::ConfigureFan(unsigned int mcode, int fanNum, GCodeBuffer& gb, StringRef& reply, bool& error) +{ + if (fanNum < 0 || fanNum >= (int)NUM_FANS) + { + reply.printf("Fan number %d is invalid, must be between 0 and %u", fanNum, NUM_FANS - 1); + error = true; + return false; + } + + return fans[fanNum].Configure(mcode, fanNum, gb, reply, error); +} + // Get current cooling fan speed on a scale between 0 and 1 float Platform::GetFanValue(size_t fan) const { @@ -2693,7 +2536,7 @@ void Platform::EnableSharedFan(bool enable) // Get current fan RPM -float Platform::GetFanRPM() +float Platform::GetFanRPM() const { // The ISR sets fanInterval to the number of microseconds it took to get fanMaxInterruptCount interrupts. // We get 2 tacho pulses per revolution, hence 2 interrupts per revolution. @@ -2726,7 +2569,7 @@ void Platform::InitFans() { #if defined(DUET_NG) || defined(__RADDS__) || defined(__ALLIGATOR__) // Set fan 1 to be thermostatic by default, monitoring all heaters except the default bed heater - fans[1].SetHeatersMonitored(((1 << HEATERS) - 1) & ~(1 << DefaultBedHeater)); + fans[1].SetHeatersMonitored(((1 << Heaters) - 1) & ~(1 << DefaultBedHeater)); fans[1].SetValue(1.0); // set it full on #else // Fan 1 on the Duet 0.8.5 shares its control pin with heater 6. Set it full on to make sure the heater (if present) is off. @@ -3026,7 +2869,7 @@ void Platform::SetPressureAdvance(size_t extruder, float factor) float Platform::ActualInstantDv(size_t drive) const { const float idv = instantDvs[drive]; - const size_t numAxes = reprap.GetGCodes().GetNumAxes(); + const size_t numAxes = reprap.GetGCodes().GetTotalAxes(); if (drive >= numAxes) { const float eComp = pressureAdvance[drive - numAxes]; @@ -3182,7 +3025,7 @@ bool Platform::GetFirmwarePin(int logicalPin, PinAccess access, Pin& firmwarePin { // Pin number out of range, so nothing to do here } - else if (logicalPin >= Heater0LogicalPin && logicalPin < Heater0LogicalPin + HEATERS) // pins 0-9 correspond to heater channels + else if (logicalPin >= Heater0LogicalPin && logicalPin < Heater0LogicalPin + (int)Heaters) // pins 0-9 correspond to heater channels { // For safety, we don't allow a heater channel to be used for servos until the heater has been disabled if (!reprap.GetHeat().IsHeaterEnabled(logicalPin - Heater0LogicalPin)) @@ -3320,6 +3163,7 @@ void Platform::GetMcuTemperatures(float& minT, float& currT, float& maxT) const #endif #ifdef DUET_NG + // Power in voltage void Platform::GetPowerVoltages(float& minV, float& currV, float& maxV) const { @@ -3327,6 +3171,16 @@ void Platform::GetPowerVoltages(float& minV, float& currV, float& maxV) const currV = AdcReadingToPowerVoltage(currentVin); maxV = AdcReadingToPowerVoltage(highestVin); } + +// TMC driver temperatures +float Platform::GetTmcDriversTemperature(unsigned int board) const +{ + const uint16_t mask = ((1u << 5) - 1) << (5 * board); // there are 5 driver son each board + return ((temperatureShutdownDrivers & mask) != 0) ? 150.0 + : ((temperatureWarningDrivers & mask) != 0) ? 100.0 + : 0.0; +} + #endif // Real-time clock @@ -3479,36 +3333,36 @@ void Platform::Tick() { case 1: case 3: - // We process a thermistor reading on alternate ticks - if (IsThermistorChannel(currentHeater)) { - // Because we are in the tick ISR and no other ISR reads the averaging filter, we can cast away 'volatile' here + // We read a thermistor channel on alternate ticks + // Because we are in the tick ISR and no other ISR reads the averaging filter, we can cast away 'volatile' here. + // The following code assumes number of thermistor channels = number of heater channels ThermistorAveragingFilter& currentFilter = const_cast<ThermistorAveragingFilter&>(thermistorFilters[currentHeater]); - currentFilter.ProcessReading(AnalogInReadChannel(thermistorAdcChannels[heaterTempChannels[currentHeater]])); - } + currentFilter.ProcessReading(AnalogInReadChannel(thermistorAdcChannels[currentHeater])); - // Guard against overly long delays between successive calls of PID::Spin(). - // Do not call Time() here, it isn't safe. We use millis() instead. - if ((configuredHeaters & (1 << currentHeater)) != 0 && (millis() - reprap.GetHeat().GetLastSampleTime(currentHeater)) > maxPidSpinDelay) - { - SetHeater(currentHeater, 0.0); - LogError(ErrorCode::BadTemp); - } + // Guard against overly long delays between successive calls of PID::Spin(). + // Do not call Time() here, it isn't safe. We use millis() instead. + if ((configuredHeaters & (1 << currentHeater)) != 0 && (millis() - reprap.GetHeat().GetLastSampleTime(currentHeater)) > maxPidSpinDelay) + { + SetHeater(currentHeater, 0.0); + LogError(ErrorCode::BadTemp); + } - ++currentHeater; - if (currentHeater == HEATERS) - { - currentHeater = 0; - } + ++currentHeater; + if (currentHeater == Heaters) + { + currentHeater = 0; + } - // If we are not using a simple modulated IR sensor, process the Z probe reading on every tick for a faster response. - // If we are using a simple modulated IR sensor then we need to allow the reading to settle after turning the IR emitter on or off, - // so on alternate ticks we read it and switch the emitter - if (zProbeType != 2) - { - const_cast<ZProbeAveragingFilter&>((tickState == 1) ? zProbeOnFilter : zProbeOffFilter).ProcessReading(GetRawZProbeReading()); + // If we are not using a simple modulated IR sensor, process the Z probe reading on every tick for a faster response. + // If we are using a simple modulated IR sensor then we need to allow the reading to settle after turning the IR emitter on or off, + // so on alternate ticks we read it and switch the emitter + if (zProbeType != 2) + { + const_cast<ZProbeAveragingFilter&>((tickState == 1) ? zProbeOnFilter : zProbeOffFilter).ProcessReading(GetRawZProbeReading()); + } + ++tickState; } - ++tickState; break; case 2: |