diff --git a/Configuration.h b/Configuration.h index fbc949a..7983867 100644 --- a/Configuration.h +++ b/Configuration.h @@ -30,7 +30,7 @@ Licence: GPL #endif #ifndef DATE -#define DATE "2015-12-30" +#define DATE "2015-12-31" #endif #define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman" diff --git a/Dictionay b/Dictionay deleted file mode 100644 index 1a68717..0000000 --- a/Dictionay +++ /dev/null @@ -1,7 +0,0 @@ -duet -thermistor -debounce -struct -arduino -extruder -deprecated diff --git a/Heat.cpp b/Heat.cpp index c769574..1bd8b15 100644 --- a/Heat.cpp +++ b/Heat.cpp @@ -22,35 +22,34 @@ Licence: GPL const float invHeatPwmAverageCount = HEAT_SAMPLE_TIME/HEAT_PWM_AVERAGE_TIME; -Heat::Heat(Platform* p) : platform(p), active(false), coldExtrude(false), - bedHeater(BED_HEATER), chamberHeater(-1) +Heat::Heat(Platform* p) : platform(p), active(false), coldExtrude(false), bedHeater(BED_HEATER), chamberHeater(-1) { - for (size_t heater = 0; heater < HEATERS; heater++) - { - pids[heater] = new PID(platform, heater); - } + for (size_t heater = 0; heater < HEATERS; heater++) + { + pids[heater] = new PID(platform, heater); + } } void Heat::Init() { - for (size_t heater = 0; heater < HEATERS; heater++) - { - pids[heater]->Init(); - } - lastTime = platform->Time(); - longWait = lastTime; - coldExtrude = false; - active = true; + for (size_t heater = 0; heater < HEATERS; heater++) + { + pids[heater]->Init(); + } + lastTime = platform->Time(); + longWait = lastTime; + coldExtrude = false; + active = true; } void Heat::Exit() { - for (size_t heater = 0; heater < HEATERS; heater++) - { - pids[heater]->SwitchOff(); - } - platform->Message(HOST_MESSAGE, "Heat class exited.\n"); - active = false; + for (size_t heater = 0; heater < HEATERS; heater++) + { + pids[heater]->SwitchOff(); + } + platform->Message(HOST_MESSAGE, "Heat class exited.\n"); + active = false; } void Heat::Spin() @@ -72,14 +71,14 @@ void Heat::Spin() void Heat::Diagnostics() { - platform->Message(GENERIC_MESSAGE, "Heat Diagnostics:\n"); - for (size_t heater=0; heater < HEATERS; heater++) - { - if (pids[heater]->active) - { - platform->MessageF(GENERIC_MESSAGE, "Heater %d: I-accumulator = %.1f\n", heater, pids[heater]->temp_iState); - } - } + platform->Message(GENERIC_MESSAGE, "Heat Diagnostics:\n"); + for (size_t heater=0; heater < HEATERS; heater++) + { + if (pids[heater]->active) + { + platform->MessageF(GENERIC_MESSAGE, "Heater %d: I-accumulator = %.1f\n", heater, pids[heater]->temp_iState); + } + } } bool Heat::AllHeatersAtSetTemperatures(bool includingBed) const @@ -87,7 +86,9 @@ bool Heat::AllHeatersAtSetTemperatures(bool includingBed) const for (int8_t heater = (includingBed) ? 0 : 1; heater < HEATERS; heater++) { if (!HeaterAtSetTemperature(heater)) + { return false; + } } return true; } @@ -96,7 +97,9 @@ bool Heat::AllHeatersAtSetTemperatures(bool includingBed) const bool Heat::HeaterAtSetTemperature(int8_t heater) const { if (pids[heater]->SwitchedOff()) // If it hasn't anything to do, it must be right wherever it is... + { return true; + } float dt = GetTemperature(heater); float target = (pids[heater]->Active()) ? GetActiveTemperature(heater) : GetStandbyTemperature(heater); @@ -111,33 +114,32 @@ PID::PID(Platform* p, int8_t h) : platform(p), heater(h) void PID::Init() { - SetHeater(0.0); - temperature = platform->GetTemperature(heater); - activeTemperature = ABS_ZERO; - standbyTemperature = ABS_ZERO; - lastTemperature = temperature; - temp_iState = 0.0; - badTemperatureCount = 0; - temperatureFault = false; - active = false; // Default to standby temperature - switchedOff = true; - heatingUp = false; - averagePWM = 0.0; + SetHeater(0.0); + temperature = platform->GetTemperature(heater); + activeTemperature = ABS_ZERO; + standbyTemperature = ABS_ZERO; + lastTemperature = temperature; + temp_iState = 0.0; + badTemperatureCount = 0; + temperatureFault = false; + active = false; // Default to standby temperature + switchedOff = true; + heatingUp = false; + averagePWM = 0.0; - // Time the sensor was last sampled. During startup, we use the current - // time as the initial value so as to not trigger an immediate warning from - // the Tick ISR. - lastSampleTime = platform->Time(); + // Time the sensor was last sampled. During startup, we use the current + // time as the initial value so as to not trigger an immediate warning from + // the Tick ISR. + lastSampleTime = platform->Time(); } void PID::SwitchOn() { -// if(reprap.Debug()) -// { -// snprintf(scratchString, STRING_LENGTH, "Heater %d switched on.\n", heater); -// platform->Message(BOTH_MESSAGE, scratchString); -// } - switchedOff = false; + if (reprap.Debug(Module::moduleHeat)) + { + platform->MessageF(GENERIC_MESSAGE, "Heater %d switched on.\n", heater); + } + switchedOff = temperatureFault; } void PID::SetHeater(float power) const @@ -147,153 +149,154 @@ void PID::SetHeater(float power) const void PID::Spin() { - // For temperature sensors which do not require frequent sampling and averaging, - // their temperature is read here and error/safety handling performed. However, - // unlike the Tick ISR, this code is not executed at interrupt level and consequently - // runs the risk of having undesirable delays between calls. To guard against this, - // we record for each PID object when it was last sampled and have the Tick ISR - // take action if there is a significant delay since the time of last sampling. - lastSampleTime = platform->Time(); + // For temperature sensors which do not require frequent sampling and averaging, + // their temperature is read here and error/safety handling performed. However, + // unlike the Tick ISR, this code is not executed at interrupt level and consequently + // runs the risk of having undesirable delays between calls. To guard against this, + // we record for each PID object when it was last sampled and have the Tick ISR + // take action if there is a significant delay since the time of last sampling. + lastSampleTime = platform->Time(); - // 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 - temperature = platform->GetTemperature(heater, &err); // In the event of an error, err is set and BAD_ERROR_TEMPERATURE is returned + Platform::TempError err = Platform::TempError::errOpen; // Initially assign an error; call should update but if it doesn't, we'll treat as an error + temperature = platform->GetTemperature(heater, &err); // In the event of an error, err is set and BAD_ERROR_TEMPERATURE is returned - // 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 - // we don't even have a thermistor connected. So don't even check for faults if we - // are not switched on. This is safe, as the next bit of code always turns our - // heater off in that case anyway. - if (temperatureFault || switchedOff) - { - SetHeater(0.0); // Make sure... - averagePWM *= (1.0 - invHeatPwmAverageCount); - return; - } + // 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 + // we don't even have a thermistor connected. So don't even check for faults if we + // are not switched on. This is safe, as the next bit of code always turns our + // heater off in that case anyway. + if (temperatureFault || switchedOff) + { + SetHeater(0.0); // Make sure... + averagePWM *= (1.0 - invHeatPwmAverageCount); + return; + } - // We are switched on. Check for faults. Temperature silly-low or silly-high mean open-circuit - // or shorted thermistor respectively. - if (temperature < BAD_LOW_TEMPERATURE || temperature > BAD_HIGH_TEMPERATURE) - { - if (platform->DoThermistorAdc(heater) || !(Platform::TempErrorPermanent(err))) - { - // Error may be a temporary error and may correct itself after a few additional reads - badTemperatureCount++; - } - else - { - // Error condition is not expected to correct itself (e.g., digital device such - // as a MAX31855 reporting that the temp sensor is shorted -- even a temporary - // short in such a situation warrants manual attention and correction). - badTemperatureCount = MAX_BAD_TEMPERATURE_COUNT + 1; - } + // We are switched on. Check for faults. Temperature silly-low or silly-high mean open-circuit + // or shorted thermistor respectively. + if (temperature < BAD_LOW_TEMPERATURE || temperature > BAD_HIGH_TEMPERATURE) + { + if (platform->DoThermistorAdc(heater) || !(Platform::TempErrorPermanent(err))) + { + // Error may be a temporary error and may correct itself after a few additional reads + badTemperatureCount++; + } + else + { + // Error condition is not expected to correct itself (e.g., digital device such + // as a MAX31855 reporting that the temp sensor is shorted -- even a temporary + // short in such a situation warrants manual attention and correction). + badTemperatureCount = MAX_BAD_TEMPERATURE_COUNT + 1; + } - if (badTemperatureCount > MAX_BAD_TEMPERATURE_COUNT) - { - SetHeater(0.0); - temperatureFault = true; - //switchedOff = true; - platform->MessageF(GENERIC_MESSAGE, "Temperature fault on heater %d%s%s, T = %.1f\n", + if (badTemperatureCount > MAX_BAD_TEMPERATURE_COUNT) + { + SetHeater(0.0); + temperatureFault = true; + //switchedOff = true; + platform->MessageF(GENERIC_MESSAGE, "Temperature fault on heater %d%s%s, T = %.1f\n", heater, (err != Platform::TempError::errOk) ? ", " : "", (err != Platform::TempError::errOk) ? Platform::TempErrorStr(err) : "", temperature); - reprap.FlagTemperatureFault(heater); - } - } - else - { + reprap.FlagTemperatureFault(heater); + } + } + else + { badTemperatureCount = 0; - } + } - // Now check how long it takes to warm up. If too long, maybe the thermistor is not in contact with the heater - if (heatingUp && heater != BED_HEATER) // FIXME - also check bed warmup time? - { - float tmp = (active) ? activeTemperature : standbyTemperature; - if (temperature < tmp - TEMPERATURE_CLOSE_ENOUGH) - { - float tim = platform->Time() - timeSetHeating; - float limit = platform->TimeToHot(); - if (tim > limit && limit > 0.0) - { - SetHeater(0.0); - temperatureFault = true; - //switchedOff = true; - platform->MessageF(GENERIC_MESSAGE, "Heating fault on heater %d, T = %.1f C; still not at temperature %.1f after %f seconds.\n", heater, temperature, tmp, tim); - reprap.FlagTemperatureFault(heater); - } - } - else - { - heatingUp = false; - } - } + // Now check how long it takes to warm up. If too long, maybe the thermistor is not in contact with the heater + if (heatingUp && heater != BED_HEATER) // FIXME - also check bed warmup time? + { + float tmp = (active) ? activeTemperature : standbyTemperature; + if (temperature < tmp - TEMPERATURE_CLOSE_ENOUGH) + { + float tim = platform->Time() - timeSetHeating; + float limit = platform->TimeToHot(); + if (tim > limit && limit > 0.0) + { + SetHeater(0.0); + temperatureFault = true; + //switchedOff = true; + platform->MessageF(GENERIC_MESSAGE, "Heating fault on heater %d, T = %.1f C; still not at temperature %.1f after %f seconds.\n", heater, temperature, tmp, tim); + reprap.FlagTemperatureFault(heater); + } + } + else + { + heatingUp = false; + } + } - float targetTemperature = (active) ? activeTemperature : standbyTemperature; - float error = targetTemperature - temperature; - const PidParameters& pp = platform->GetPidParameters(heater); - - if (!pp.UsePID()) - { - float heaterValue = (error > 0.0) ? min(pp.kS, 1.0) : 0.0; - SetHeater(heaterValue); - averagePWM = averagePWM * (1.0 - invHeatPwmAverageCount) + heaterValue; - return; - } - - if(error < -pp.fullBand) - { - // actual temperature is well above target - temp_iState = (targetTemperature + pp.fullBand - 25.0) * pp.kT; // set the I term to our estimate of what will be needed ready for the switch to PID - SetHeater(0.0); - averagePWM *= (1.0 - invHeatPwmAverageCount); - lastTemperature = temperature; - return; - } - if(error > pp.fullBand) - { - // actual temperature is well below target - temp_iState = (targetTemperature - pp.fullBand - 25.0) * pp.kT; // set the I term to our estimate of what will be needed ready for the switch to PID - float heaterValue = min(pp.kS, 1.0); - SetHeater(heaterValue); - averagePWM = averagePWM * (1.0 - invHeatPwmAverageCount) + heaterValue; - lastTemperature = temperature; - return; - } - - float sampleInterval = platform->HeatSampleTime(); - temp_iState += error * pp.kI * sampleInterval; - - if (temp_iState < pp.pidMin) - { - temp_iState = pp.pidMin; - } - else if (temp_iState > pp.pidMax) - { - temp_iState = pp.pidMax; - } - - float temp_dState = pp.kD * (temperature - lastTemperature) / sampleInterval; - float result = (pp.kP * error + temp_iState - temp_dState) * pp.kS / 255.0; + float targetTemperature = (active) ? activeTemperature : standbyTemperature; + float error = targetTemperature - temperature; + const PidParameters& pp = platform->GetPidParameters(heater); - lastTemperature = temperature; + if (!pp.UsePID()) + { + float heaterValue = (error > 0.0) ? min(pp.kS, 1.0) : 0.0; + SetHeater(heaterValue); + averagePWM = averagePWM * (1.0 - invHeatPwmAverageCount) + heaterValue; + return; + } - if (result < 0.0) - { - result = 0.0; - } - else if (result > 1.0) - { - result = 1.0; - } + if (error < -pp.fullBand) + { + // actual temperature is well above target + temp_iState = (targetTemperature + pp.fullBand - 25.0) * pp.kT; // set the I term to our estimate of what will be needed ready for the switch to PID + SetHeater(0.0); + averagePWM *= (1.0 - invHeatPwmAverageCount); + lastTemperature = temperature; + return; + } - if (!temperatureFault) - { - SetHeater(result); - } + if (error > pp.fullBand) + { + // actual temperature is well below target + temp_iState = (targetTemperature - pp.fullBand - 25.0) * pp.kT; // set the I term to our estimate of what will be needed ready for the switch to PID + float heaterValue = min(pp.kS, 1.0); + SetHeater(heaterValue); + averagePWM = averagePWM * (1.0 - invHeatPwmAverageCount) + heaterValue; + lastTemperature = temperature; + return; + } - averagePWM = averagePWM * (1.0 - invHeatPwmAverageCount) + result; + float sampleInterval = platform->HeatSampleTime(); + temp_iState += error * pp.kI * sampleInterval; + + if (temp_iState < pp.pidMin) + { + temp_iState = pp.pidMin; + } + else if (temp_iState > pp.pidMax) + { + temp_iState = pp.pidMax; + } + + float temp_dState = pp.kD * (temperature - lastTemperature) / sampleInterval; + float result = (pp.kP * error + temp_iState - temp_dState) * pp.kS / 255.0; + + lastTemperature = temperature; + + if (result < 0.0) + { + result = 0.0; + } + else if (result > 1.0) + { + result = 1.0; + } + + if (!temperatureFault) + { + SetHeater(result); + } + + averagePWM = averagePWM * (1.0 - invHeatPwmAverageCount) + 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); } @@ -304,4 +307,3 @@ float PID::GetAveragePWM() const } // End - diff --git a/Libraries/Lwip/lwipopts.h b/Libraries/Lwip/lwipopts.h index cebbdd8..72dbceb 100644 --- a/Libraries/Lwip/lwipopts.h +++ b/Libraries/Lwip/lwipopts.h @@ -137,14 +137,14 @@ a lot of data that needs to be copied, this should be set high. */ #define LWIP_TCP (1) #define TCP_TTL (255) /* TCP receive window. */ -#define TCP_WND (2 * 1432) +#define TCP_WND (2 * 1460) /* Controls if TCP should queue segments that arrive out of order. Define to 0 if your device is low on memory. */ #define TCP_QUEUE_OOSEQ 1 /* TCP Maximum segment size. */ -#define TCP_MSS (1432) // 1432 is optimal for Windows clients +#define TCP_MSS (1460) // 1432 is optimal for Windows clients /* TCP sender buffer space (bytes). */ -#define TCP_SND_BUF (2 * 1432) //changed from 2150 to pass LWIP sanity checks +#define TCP_SND_BUF (2 * 1460) //changed from 2150 to pass LWIP sanity checks /* TCP sender buffer space (pbufs). This must be at least = 2 * TCP_SND_BUF/TCP_MSS for things to work. */ #define TCP_SND_QUEUELEN (3 * TCP_SND_BUF / TCP_MSS) /* Maximum number of retransmissions of data segments. */ diff --git a/PrintMonitor.cpp b/PrintMonitor.cpp index 6a405c7..f536da1 100644 --- a/PrintMonitor.cpp +++ b/PrintMonitor.cpp @@ -470,7 +470,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod } // Go to the last sector and proceed from there on - const FilePosition seekFromEnd = fileBeingParsed->Length() % GCODE_READ_SIZE; + const FilePosition seekFromEnd = ((fileBeingParsed->Length() - 1) % GCODE_READ_SIZE) + 1; fileBeingParsed->Seek(fileBeingParsed->Length() - seekFromEnd); fileOverlapLength = 0; parseState = parsingFooter; diff --git a/Release/RepRapFirmware-1.09p-alpha-dc42.bin b/Release/RepRapFirmware-1.09p-alpha-dc42.bin new file mode 100644 index 0000000..219b42c Binary files /dev/null and b/Release/RepRapFirmware-1.09p-alpha-dc42.bin differ diff --git a/Webserver.cpp b/Webserver.cpp index 7edbf17..a6ca1c9 100644 --- a/Webserver.cpp +++ b/Webserver.cpp @@ -209,7 +209,7 @@ void Webserver::Spin() { telnetInterpreter->SendGCodeReply(transaction); } - // Process other messages (unless this is an HTTP request which may need special treatement) + // Process other messages (unless this is an HTTP request which may need special treatment) else if (interpreter != httpInterpreter || httpInterpreter->IsReady()) { for(size_t i = 0; i < 500; i++) @@ -236,6 +236,7 @@ void Webserver::Spin() } } } + // else the HTTP server is not ready } else { @@ -1042,6 +1043,10 @@ bool Webserver::HttpInterpreter::NeedMoreData() // At this stage we've processed the first chunk of a POST upload request. Store the // initial payload and reset the HTTP reader again in order to process new requests WriteUploadedData(clientMessage + (clientPointer - uploadedBytes), uploadedBytes); + if (reprap.Debug(moduleWebserver)) + { + platform->MessageF(HOST_MESSAGE, "Wrote %lu bytes of file\n", uploadedBytes); + } ResetState(); return false; } @@ -1228,7 +1233,6 @@ bool Webserver::HttpInterpreter::CharFromClient(char c) case '\t': clientMessage[clientPointer++] = 0; qualifiers[numQualKeys].key = clientMessage + clientPointer; // so that we can read the whole value even if it contains a null - ++numCommandWords; commandWords[numCommandWords] = clientMessage + clientPointer; state = doingCommandWord; break; @@ -1431,12 +1435,18 @@ bool Webserver::HttpInterpreter::ProcessMessage() { if (reprap.Debug(moduleWebserver)) { - platform->MessageF(HOST_MESSAGE, "HTTP requests with %d command words:", numCommandWords); + platform->Message(HOST_MESSAGE, "HTTP req, command words {"); for (size_t i = 0; i < numCommandWords; ++i) { platform->MessageF(HOST_MESSAGE, " %s", commandWords[i]); } - platform->Message(HOST_MESSAGE, "\n"); + platform->Message(HOST_MESSAGE, " }, parameters {"); + + for (size_t i = 0; i < numQualKeys; ++i) + { + platform->MessageF(HOST_MESSAGE, " %s=%s", qualifiers[i].key, qualifiers[i].value); + } + platform->Message(HOST_MESSAGE, " }\n"); } if (numCommandWords < 2) @@ -1498,6 +1508,10 @@ bool Webserver::HttpInterpreter::ProcessMessage() FileStore *file = platform->GetFileStore("0:/", qualifiers[0].value, true); if (StartUpload(file)) { + if (reprap.Debug(moduleWebserver)) + { + platform->MessageF(HOST_MESSAGE, "Start uploading file %s length %lu\n", qualifiers[0].value, postFileLength); + } // Start new file upload uploadingTextData = false; uploadedBytes = numContinuationBytes = 0; @@ -2307,27 +2321,28 @@ void Webserver::FtpInterpreter::ProcessLine() else if (StringStartsWith(clientMessage, "RETR")) { ReadFilename(4); - FileStore *fs = platform->GetFileStore(currentDir, filename, false); + FileStore *file = platform->GetFileStore(currentDir, filename, false); - if (fs == nullptr) + if (file == nullptr) { SendReply(550, "Failed to open file."); } else { - snprintf(ftpResponse, ftpResponseLength, "Opening data connection for %s (%lu bytes).", filename, fs->Length()); + snprintf(ftpResponse, ftpResponseLength, "Opening data connection for %s (%lu bytes).", filename, file->Length()); SendReply(150, ftpResponse); if (network->AcquireDataTransaction()) { // send the file via data port NetworkTransaction *dataTransaction = network->GetTransaction(); - dataTransaction->SetFileToWrite(fs); + dataTransaction->SetFileToWrite(file); dataTransaction->Commit(false); state = doingPasvIO; } else { + file->Close(); SendReply(500, "Unknown error."); network->CloseDataPort(); state = authenticated;