#include "Gcode.h"
#include "TemperatureControl.h"
#include "libs/StreamOutput.h"
+#include "TemperatureControlPublicAccess.h"
+#include "PublicDataRequest.h"
+#include "PublicData.h"
#include <cmath> // std::abs
PID_Autotuner::PID_Autotuner()
{
- t = NULL;
+ temp_control = NULL;
s = NULL;
lastInputs = NULL;
peaks = NULL;
tick = false;
- tickCnt= 0;
+ tickCnt = 0;
}
void PID_Autotuner::on_module_loaded()
register_for_event(ON_GCODE_RECEIVED);
}
-void PID_Autotuner::begin(TemperatureControl *temp, float target, StreamOutput *stream, int ncycles)
+void PID_Autotuner::begin(float target, StreamOutput *stream, int ncycles)
{
noiseBand = 0.5;
- oStep = temp->heater_pin.max_pwm(); // use max pwm to cycle temp
+ oStep = temp_control->heater_pin.max_pwm(); // use max pwm to cycle temp
nLookBack = 5 * 20; // 5 seconds of lookback
- lookBackCnt= 0;
- tickCnt= 0;
+ lookBackCnt = 0;
+ tickCnt = 0;
if (lastInputs != NULL) delete[] lastInputs;
- lastInputs = new float[nLookBack+1];
- t = temp;
+ lastInputs = new float[nLookBack + 1];
+
s = stream;
- t->heater_pin.set(0);
- t->target_temperature = 0.0;
+ temp_control->heater_pin.set(0);
+ temp_control->target_temperature = 0.0;
target_temperature = target;
requested_cycles = ncycles;
peakCount = 0;
justchanged = false;
- float refVal = t->get_temperature();
+ float refVal = temp_control->get_temperature();
absMax = refVal;
absMin = refVal;
- output= oStep;
- t->heater_pin.pwm(oStep); // turn on to start heating
+ output = oStep;
+ temp_control->heater_pin.pwm(oStep); // turn on to start heating
- s->printf("%s: Starting PID Autotune, %d max cycles, M304 aborts\n", t->designator.c_str(), ncycles);
+ s->printf("%s: Starting PID Autotune, %d max cycles, M304 aborts\n", temp_control->designator.c_str(), ncycles);
}
void PID_Autotuner::abort()
{
- if (!t)
+ if (temp_control == NULL)
return;
- t->target_temperature = 0;
- t->heater_pin.set(0);
- t = NULL;
+ temp_control->target_temperature = 0;
+ temp_control->heater_pin.set(0);
+ temp_control = NULL;
if (s)
s->printf("PID Autotune Aborted\n");
{
Gcode *gcode = static_cast<Gcode *>(argument);
- if ((gcode->has_m) && (gcode->m == 304))
- abort();
+ if(gcode->has_m) {
+ if(gcode->m == 304) {
+ gcode->mark_as_taken();
+ abort();
+
+ } else if (gcode->m == 303 && gcode->has_letter('E')) {
+ gcode->mark_as_taken();
+ int pool_index = gcode->get_value('E');
+
+ // get the temperature control instance with this pool index
+ void *returned_data;
+ bool ok = THEKERNEL->public_data->get_value( temperature_control_checksum, pool_index_checksum, pool_index, &returned_data );
+
+ if (ok) {
+ this->temp_control = static_cast<TemperatureControl *>(returned_data);
+
+ } else {
+ gcode->stream->printf("No temperature control with index %d found\r\n", pool_index);
+ return;
+ }
+
+ float target = 150.0;
+ if (gcode->has_letter('S')) {
+ target = gcode->get_value('S');
+ gcode->stream->printf("Target: %5.1f\n", target);
+ }
+ int ncycles = 8;
+ if (gcode->has_letter('C')) {
+ ncycles = gcode->get_value('C');
+ }
+ gcode->stream->printf("Start PID tune for E%d\n", pool_index);
+ this->begin(target, gcode->stream, ncycles);
+ }
+ }
}
uint32_t PID_Autotuner::on_tick(uint32_t dummy)
{
- if (t)
+ if (temp_control != NULL)
tick = true;
- tickCnt += 1000/20; // millisecond tick count
+
+ tickCnt += 1000 / 20; // millisecond tick count
return 0;
}
tick = false;
- if (t == NULL)
+ if (temp_control == NULL)
return;
if(peakCount >= requested_cycles) {
return;
}
- float refVal = t->get_temperature();
+ float refVal = temp_control->get_temperature();
if (refVal > absMax) absMax = refVal;
if (refVal < absMin) absMin = refVal;
// oscillate the output base on the input's relation to the setpoint
- if (refVal > target_temperature + noiseBand){
- output= 0;
- //t->heater_pin.pwm(output);
- t->heater_pin.set(0);
+ if (refVal > target_temperature + noiseBand) {
+ output = 0;
+ //temp_control->heater_pin.pwm(output);
+ temp_control->heater_pin.set(0);
} else if (refVal < target_temperature - noiseBand) {
- output= oStep;
- t->heater_pin.pwm(output);
+ output = oStep;
+ temp_control->heater_pin.pwm(output);
}
bool isMax = true, isMin = true;
if (justchanged && peakCount > 2) {
if(peakCount == 3) { // reset min to new min
- absMin= refVal;
+ absMin = refVal;
}
//we've transitioned. check if we can autotune based on the last peaks
float avgSeparation = (std::abs(peaks[peakCount - 1] - peaks[peakCount - 2]) + std::abs(peaks[peakCount - 2] - peaks[peakCount - 3])) / 2;
justchanged = false;
if ((tickCnt % 1000) == 0) {
- s->printf("%s: %5.1f/%5.1f @%d %d/%d\n", t->designator.c_str(), t->get_temperature(), target_temperature, output, peakCount, requested_cycles);
+ s->printf("%s: %5.1f/%5.1f @%d %d/%d\n", temp_control->designator.c_str(), temp_control->get_temperature(), target_temperature, output, peakCount, requested_cycles);
DEBUG_PRINTF("lookBackCnt= %d, peakCount= %d, absmax= %g, absmin= %g, peak1= %lu, peak2= %lu\n", lookBackCnt, peakCount, absMax, absMin, peak1, peak2);
}
}
void PID_Autotuner::finishUp()
{
//we can generate tuning parameters!
- float Ku = 4*(2*oStep)/((absMax-absMin)*3.14159);
- float Pu = (float)(peak1-peak2) / 1000;
+ float Ku = 4 * (2 * oStep) / ((absMax - absMin) * 3.14159);
+ float Pu = (float)(peak1 - peak2) / 1000;
s->printf("\tKu: %g, Pu: %g\n", Ku, Pu);
float kp = 0.6 * Ku;
s->printf("\tTrying:\n\tKp: %5.1f\n\tKi: %5.3f\n\tKd: %5.0f\n", kp, ki, kd);
- t->setPIDp(kp);
- t->setPIDi(ki);
- t->setPIDd(kd);
+ temp_control->setPIDp(kp);
+ temp_control->setPIDi(ki);
+ temp_control->setPIDd(kd);
s->printf("PID Autotune Complete! The settings above have been loaded into memory, but not written to your config file.\n");
// and clean up
- t->target_temperature = 0;
- t->heater_pin.set(0);
- t = NULL;
+ temp_control->target_temperature = 0;
+ temp_control->heater_pin.set(0);
+ temp_control = NULL;
s = NULL;
if (peaks != NULL)