diff --git a/Release/Duet-Ethernet/Edge/DuetEthernetFirmware-1.19beta4.bin b/Release/Duet-Ethernet/Edge/DuetEthernetFirmware-1.19beta5.bin similarity index 63% rename from Release/Duet-Ethernet/Edge/DuetEthernetFirmware-1.19beta4.bin rename to Release/Duet-Ethernet/Edge/DuetEthernetFirmware-1.19beta5.bin index b440384..04406ab 100644 Binary files a/Release/Duet-Ethernet/Edge/DuetEthernetFirmware-1.19beta4.bin and b/Release/Duet-Ethernet/Edge/DuetEthernetFirmware-1.19beta5.bin differ diff --git a/Release/Duet-WiFi/Edge/DuetWiFiFirmware-1.19beta4.bin b/Release/Duet-WiFi/Edge/DuetWiFiFirmware-1.19beta5.bin similarity index 61% rename from Release/Duet-WiFi/Edge/DuetWiFiFirmware-1.19beta4.bin rename to Release/Duet-WiFi/Edge/DuetWiFiFirmware-1.19beta5.bin index 0711fb9..873cecc 100644 Binary files a/Release/Duet-WiFi/Edge/DuetWiFiFirmware-1.19beta4.bin and b/Release/Duet-WiFi/Edge/DuetWiFiFirmware-1.19beta5.bin differ diff --git a/src/Configuration.h b/src/Configuration.h index b44cf3a..abde541 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -105,12 +105,13 @@ static_assert(DefaultMaxTempExcursion > TEMPERATURE_CLOSE_ENOUGH, "DefaultMaxTem // Temperature sense channels const unsigned int FirstThermocoupleChannel = 100; // Temperature sensor channels 100... are thermocouples const unsigned int FirstRtdChannel = 200; // Temperature sensor channels 200... are RTDs +const unsigned int FirstLinearAdcChannel = 300; // Temperature sensor channels 300... use an ADC that provides a linear output over a temperature range // PWM frequencies const unsigned int SlowHeaterPwmFreq = 10; // slow PWM frequency for bed and chamber heaters, compatible with DC/AC SSRs const unsigned int NormalHeaterPwmFreq = 250; // normal PWM frequency used for hot ends const unsigned int DefaultFanPwmFreq = 250; // increase to 25kHz using M106 command to meet Intel 4-wire PWM fan specification -const unsigned int DefaultPinWritePwmFreq = 500; // default PWM frequency for M42 pin writes and extrusion ancilliary PWM +const unsigned int DefaultPinWritePwmFreq = 500; // default PWM frequency for M42 pin writes and extrusion ancillary PWM // Default Z probe values diff --git a/src/DuetNG/NetworkResponder.cpp b/src/DuetNG/NetworkResponder.cpp index 59514c0..aea2b22 100644 --- a/src/DuetNG/NetworkResponder.cpp +++ b/src/DuetNG/NetworkResponder.cpp @@ -177,6 +177,7 @@ void NetworkResponder::ConnectionLost() { CancelUpload(); OutputBuffer::ReleaseAll(outBuf); + outBuf = nullptr; outStack->ReleaseAll(); if (fileBeingSent != nullptr) diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 90804d6..f26160b 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -3147,6 +3147,7 @@ void GCodes::SetHeaterParameters(GCodeBuffer& gb, StringRef& reply) if ( (0 <= thermistor && thermistor < HEATERS) || ((int)FirstThermocoupleChannel <= thermistor && thermistor < (int)(FirstThermocoupleChannel + MaxSpiTempSensors)) || ((int)FirstRtdChannel <= thermistor && thermistor < (int)(FirstRtdChannel + MaxSpiTempSensors)) + || ((int)FirstLinearAdcChannel <= thermistor && thermistor < (int)(FirstLinearAdcChannel + MaxSpiTempSensors)) ) { platform.SetThermistorNumber(heater, thermistor); diff --git a/src/Heating/TemperatureSensor.cpp b/src/Heating/TemperatureSensor.cpp index 2d58701..74a9c39 100644 --- a/src/Heating/TemperatureSensor.cpp +++ b/src/Heating/TemperatureSensor.cpp @@ -48,16 +48,19 @@ const uint32_t MAX31855_Frequency = 4000000; // maximum for MAX31855 is 5MHz const uint32_t MAX31865_Frequency = 4000000; // maximum for MAX31865 is also 5MHz +const uint32_t MCP3204_Frequency = 1000000; // maximum for MCP3204 is 1MHz @ 2.7V, will be slightly higher at 3.3V // SPI modes: // If the inactive state of SCL is LOW (CPOL = 0) (in the case of the MAX31865, this is sampled on the falling edge of CS): -// The MAX31855 sets up the first data bit after the falling edge of CS, and changes the data on each falling clock edge. +// The MAX31855 sets up the first data bit after the falling edge of CLK, and changes the data on each falling clock edge. // So the SAM needs to sample data on the rising clock edge. This requires NCPHA = 1. -// The MAX31865 changes data after the rising edge of CS, and samples input data on the falling edge. +// The MAX31865 changes data after the rising edge of CLK, and samples input data on the falling edge. // This requires NCPHA = 0. +// The MCP3204 samples input data on the rising edge and changes the output data on the rising edge. const uint8_t MAX31855_SpiMode = SPI_MODE_0; const uint8_t MAX31865_SpiMode = SPI_MODE_1; +const uint8_t MCP3204_SpiMode = SPI_MODE_0; // Define the minimum interval between readings. The MAX31865 needs 62.5ms in 50Hz filter mode. const uint32_t MinimumReadInterval = 100; // minimum interval between reads, in milliseconds @@ -175,11 +178,38 @@ TemperatureError TemperatureSensor::TryInitRtd() const : sts; } -TemperatureError TemperatureSensor::GetThermocoupleTemperature(float *t) +// Initialise the linear ADC +void TemperatureSensor::InitLinearAdc(uint8_t cs) +{ + device.csPin = cs; + device.spiMode = MCP3204_SpiMode; + device.clockFrequency = MCP3204_Frequency; + sspi_master_init(&device, 8); + + for (unsigned int i = 0; i < 3; ++i) // try 3 times + { + TryGetLinearAdcTemperature(); + if (lastResult == TemperatureError::success) + { + break; + } + delay(MinimumReadInterval); + } + + lastReadingTime = millis(); + + if (lastResult != TemperatureError::success) + { + reprap.GetPlatform().MessageF(GENERIC_MESSAGE, "Error: failed to initialise daughter board ADC: %s\n", TemperatureErrorString(lastResult)); + } + +} + +TemperatureError TemperatureSensor::GetThermocoupleTemperature(float& t) { if (inInterrupt() || millis() - lastReadingTime < MinimumReadInterval) { - *t = lastTemperature; + t = lastTemperature; } else { @@ -247,7 +277,7 @@ TemperatureError TemperatureSensor::GetThermocoupleTemperature(float *t) rawVal |= (0 - (rawVal & 0x2000)); // sign-extend the sign bit // And convert to from units of 1/4C to 1C - *t = lastTemperature = (float)(0.25 * (float)(int32_t)rawVal); + t = lastTemperature = (float)(0.25 * (float)(int32_t)rawVal); lastResult = TemperatureError::success; } } @@ -255,11 +285,11 @@ TemperatureError TemperatureSensor::GetThermocoupleTemperature(float *t) return lastResult; } -TemperatureError TemperatureSensor::GetRtdTemperature(float *t) +TemperatureError TemperatureSensor::GetRtdTemperature(float& t) { if (inInterrupt() || millis() - lastReadingTime < MinimumReadInterval) { - *t = lastTemperature; + t = lastTemperature; } else { @@ -325,7 +355,7 @@ TemperatureError TemperatureSensor::GetRtdTemperature(float *t) else { const float interpolationFraction = (float)(adcVal - tempTable[low - 1].adcReading)/(float)(tempTable[low].adcReading - tempTable[low - 1].adcReading); - *t = lastTemperature = ((float)(tempTable[low].temperature - tempTable[low - 1].temperature) * interpolationFraction) + t = lastTemperature = ((float)(tempTable[low].temperature - tempTable[low - 1].temperature) * interpolationFraction) + (float)tempTable[low - 1].temperature; //debugPrintf("raw %u low %u interp %f temp %f\n", adcVal, low, interpolationFraction, *t); lastResult = TemperatureError::success; @@ -336,6 +366,49 @@ TemperatureError TemperatureSensor::GetRtdTemperature(float *t) return lastResult; } +TemperatureError TemperatureSensor::GetLinearAdcTemperature(float& t) +{ + if (!inInterrupt() && millis() - lastReadingTime >= MinimumReadInterval) + { + TryGetLinearAdcTemperature(); + } + + t = lastTemperature; + return lastResult; +} + +// Try to get a temperature reading from the linear ADC by doing an SPI transaction +void TemperatureSensor::TryGetLinearAdcTemperature() +{ + // The MCP3204 waits for a high input input bit before it does anything. Call this clock 1. + // The next input bit it high for single-ended operation, low for differential. This is clock 2. + // The next 3 input bits are the channel selection bits. These are clocks 3..5. + // Clock 6 produces a null bit on its trailing edge, which is read by the processor on clock 7. + // Clocks 7..18 produce data bits B11..B0 on their trailing edges, which are read by the MCU on the leading edges of clocks 8-19. + // If we supply further clocks, then clocks 18..29 are the same data but LSB first, omitting bit 0. + // Clocks 30 onwards will be zeros. + // So we need to use at least 19 clocks. We round this up to 24 clocks, and we check that the extra 5 bits we receive are the 5 least significant data bits in reverse order. + + static const uint8_t adcData[] = { 0xC0, 0x00, 0x00 }; // start bit, single ended, channel 0 + uint32_t rawVal; + lastResult = DoSpiTransaction(adcData, 3, rawVal); + //debugPrintf("ADC data %u\n", rawVal); + + if (lastResult == TemperatureError::success) + { + const uint32_t adcVal1 = (rawVal >> 5) & ((1 << 13) - 1); + const uint32_t adcVal2 = ((rawVal & 1) << 5) | ((rawVal & 2) << 3) | ((rawVal & 4) << 1) | ((rawVal & 8) >> 1) | ((rawVal & 16) >> 3) | ((rawVal & 32) >> 5); + if (adcVal1 >= 4096 || adcVal2 != (adcVal1 & ((1 << 6) - 1))) + { + lastResult = TemperatureError::badResponse; + } + else + { + lastTemperature = MinLinearAdcTemp + (LinearAdcDegCPerCount * (float)adcVal1); + } + } +} + // Send and receive 1 to 4 bytes of data and return the result as a single 32-bit word TemperatureError TemperatureSensor::DoSpiTransaction(const uint8_t dataOut[], size_t nbytes, uint32_t& rslt) const { diff --git a/src/Heating/TemperatureSensor.h b/src/Heating/TemperatureSensor.h index 38cb5e3..d54338d 100644 --- a/src/Heating/TemperatureSensor.h +++ b/src/Heating/TemperatureSensor.h @@ -11,17 +11,23 @@ public: TemperatureSensor() {} void InitThermocouple(uint8_t cs); void InitRtd(uint8_t cs); - TemperatureError GetThermocoupleTemperature(float *temp); - TemperatureError GetRtdTemperature(float *temp); + void InitLinearAdc(uint8_t cs); + TemperatureError GetThermocoupleTemperature(float& t); + TemperatureError GetRtdTemperature(float& t); + TemperatureError GetLinearAdcTemperature(float& t); private: TemperatureError DoSpiTransaction(const uint8_t dataOut[], size_t nbytes, uint32_t& rslt) const; TemperatureError TryInitRtd() const; + void TryGetLinearAdcTemperature(); sspi_device device; uint32_t lastReadingTime; float lastTemperature; TemperatureError lastResult; + + static constexpr float MinLinearAdcTemp = 385.0 - (1600.0 - 385.0) * (4.0/16.0); + static constexpr float LinearAdcDegCPerCount = (1600.0 - 385.0)/3200.0; }; #endif // TEMPERATURESENSOR_H diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp index 0d6fe1b..1dade00 100644 --- a/src/OutputMemory.cpp +++ b/src/OutputMemory.cpp @@ -408,7 +408,7 @@ size_t OutputBuffer::EncodeReply(OutputBuffer *src, bool allowControlChars) /*static */ OutputBuffer *OutputBuffer::Release(OutputBuffer *buf) { const irqflags_t flags = cpu_irq_save(); - OutputBuffer *nextBuffer = buf->next; + OutputBuffer * const nextBuffer = buf->next; // If this one is reused by another piece of code, don't free it up if (buf->references > 1) diff --git a/src/Platform.cpp b/src/Platform.cpp index 52e2222..ec31cae 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -640,6 +640,10 @@ void Platform::SetThermistorNumber(size_t heater, size_t thermistor) { 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); } @@ -2067,7 +2071,7 @@ float Platform::GetTemperature(size_t heater, TemperatureError& err) { // MAX31855 thermocouple chip float temp; - err = SpiTempSensors[heaterTempChannels[heater] - FirstThermocoupleChannel].GetThermocoupleTemperature(&temp); + err = SpiTempSensors[heaterTempChannels[heater] - FirstThermocoupleChannel].GetThermocoupleTemperature(temp); return (err == TemperatureError::success) ? temp : BAD_ERROR_TEMPERATURE; } @@ -2075,7 +2079,15 @@ float Platform::GetTemperature(size_t heater, TemperatureError& err) { // MAX31865 RTD chip float temp; - err = SpiTempSensors[heaterTempChannels[heater] - FirstRtdChannel].GetRtdTemperature(&temp); + err = SpiTempSensors[heaterTempChannels[heater] - FirstRtdChannel].GetRtdTemperature(temp); + return (err == TemperatureError::success) ? temp : BAD_ERROR_TEMPERATURE; + } + + if (IsLinearAdcChannel(heater)) + { + // MAX31865 RTD chip + float temp; + err = SpiTempSensors[heaterTempChannels[heater] - FirstRtdChannel].GetLinearAdcTemperature(temp); return (err == TemperatureError::success) ? temp : BAD_ERROR_TEMPERATURE; } @@ -2929,9 +2941,9 @@ void Platform::Message(const MessageType type, OutputBuffer *buffer) break; case HOST_MESSAGE: - if (!SERIAL_MAIN_DEVICE + if ( !SERIAL_MAIN_DEVICE #if SUPPORT_SCANNER - || (reprap.GetScanner().IsRegistered() && !reprap.GetScanner().DoingGCodes()) + || (reprap.GetScanner().IsRegistered() && !reprap.GetScanner().DoingGCodes()) #endif ) { diff --git a/src/Platform.h b/src/Platform.h index c38aa0e..409c231 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -537,6 +537,9 @@ public: bool IsRtdChannel(uint8_t heater) const pre(heater < HEATERS); + bool IsLinearAdcChannel(uint8_t heater) const + pre(heater < HEATERS); + void UpdateConfiguredHeaters(); bool AnyHeaterHot(uint16_t heaters, float t); // called to see if we need to turn on the hot end fan @@ -1158,6 +1161,12 @@ inline bool Platform::IsRtdChannel(uint8_t heater) const && heaterTempChannels[heater] - FirstRtdChannel < MaxSpiTempSensors; } +inline bool Platform::IsLinearAdcChannel(uint8_t heater) const +{ + return heaterTempChannels[heater] >= FirstLinearAdcChannel + && heaterTempChannels[heater] - FirstLinearAdcChannel < MaxSpiTempSensors; +} + inline const uint8_t* Platform::GetIPAddress() const { return ipAddress; diff --git a/src/RepRap.cpp b/src/RepRap.cpp index 5b15e01..e727bf5 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -489,7 +489,9 @@ void RepRap::Tick() // We can't set motor currents to 0 here because that requires interrupts to be working, and we are in an ISR } - platform->SoftwareReset((uint16_t)SoftwareResetReason::stuckInSpin); + // We now save the stack when we get stuck in a spin loop + register const uint32_t * stackPtr asm ("sp"); + platform->SoftwareReset((uint16_t)SoftwareResetReason::stuckInSpin, stackPtr + 5); } } } diff --git a/src/Version.h b/src/Version.h index 13ef597..d12c031 100644 --- a/src/Version.h +++ b/src/Version.h @@ -9,11 +9,11 @@ #define SRC_VERSION_H_ #ifndef VERSION -# define VERSION "1.19beta4" +# define VERSION "1.19beta5" #endif #ifndef DATE -# define DATE "2017-06-01" +# define DATE "2017-06-04" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"