Added buffer for averaging of measurements to improve PID robustness.
authorhakalan <hakan.langemark@gmail.com>
Fri, 18 Apr 2014 22:42:02 +0000 (00:42 +0200)
committerhakalan <hakan.langemark@gmail.com>
Fri, 18 Apr 2014 22:42:02 +0000 (00:42 +0200)
Also ignore occasional failed measurements from the thermocouple.
Formatting changes.

src/modules/tools/temperaturecontrol/TempSensor.h
src/modules/tools/temperaturecontrol/TemperatureControl.cpp
src/modules/tools/temperaturecontrol/TemperatureControl.h
src/modules/tools/temperaturecontrol/Thermistor.cpp
src/modules/tools/temperaturecontrol/Thermistor.h
src/modules/tools/temperaturecontrol/max31855.cpp
src/modules/tools/temperaturecontrol/max31855.h

index 592acd7..767f908 100644 (file)
 class TempSensor
 {
 public:
-               // Load config parameters using provided "base" names.
-               virtual void UpdateConfig(uint16_t module_checksum, uint16_t name_checksum) = 0;
+    // Load config parameters using provided "base" names.
+    virtual void UpdateConfig(uint16_t module_checksum, uint16_t name_checksum) {};
 
-               // Return temperature in degrees Celsius.
-        virtual float get_temperature() = 0;
+    // Return temperature in degrees Celsius.
+    virtual float get_temperature() { return -1.f; };
 
-               // Make sure the interface provides a destructor.
-               virtual ~TempSensor() {}
+    // Make sure the interface provides a destructor.
+    virtual ~TempSensor() {}
 };
 
 #endif
index 6a5382b..fed832b 100644 (file)
 
 
 TemperatureControl::TemperatureControl(uint16_t name) :
-  name_checksum(name), waiting(false), min_temp_violated(false) {}
+  sensor(nullptr), name_checksum(name), waiting(false), min_temp_violated(false)
+{
+}
 
+TemperatureControl::~TemperatureControl()
+{
+    delete sensor;
+}
+  
 void TemperatureControl::on_module_loaded(){
 
     // We start not desiring any temp
@@ -70,8 +77,6 @@ void TemperatureControl::on_module_loaded(){
     // Settings
     this->on_config_reload(this);
 
-    this->acceleration_factor = 10;
-
     // Register for events
     register_for_event(ON_CONFIG_RELOAD);
     this->register_for_event(ON_GCODE_EXECUTE);
@@ -100,21 +105,26 @@ void TemperatureControl::on_config_reload(void* argument){
 
     this->designator          = THEKERNEL->config->value(temperature_control_checksum, this->name_checksum, designator_checksum)->by_default(string("T"))->as_string();
 
-       // For backward compatibility, default to a thermistor sensor.
-       std::string sensor_type = THEKERNEL->config->value(temperature_control_checksum, this->name_checksum, sensor_checksum)->by_default("thermistor")->as_string();
-
-       // Instantiate correct sensor (TBD: TempSensor factory?)
-       if(sensor_type.compare("thermistor") == 0)
-       {
-               sensor.reset(new Thermistor());
-       }
-       else if(sensor_type.compare("max31855") == 0)
-       {
-               sensor.reset(new Max31855());
-       }
-
-       sensor->UpdateConfig(temperature_control_checksum, this->name_checksum);
-       
+    // For backward compatibility, default to a thermistor sensor.
+    std::string sensor_type = THEKERNEL->config->value(temperature_control_checksum, this->name_checksum, sensor_checksum)->by_default("thermistor")->as_string();
+
+    // Instantiate correct sensor (TBD: TempSensor factory?)
+    delete sensor;
+    sensor = nullptr; // In case we fail to create a new sensor.
+    if(sensor_type.compare("thermistor") == 0)
+    {
+        sensor = new Thermistor();
+    }
+    else if(sensor_type.compare("max31855") == 0)
+    {
+        sensor = new Max31855();
+    }
+    else
+    {
+        sensor = new TempSensor(); // A dummy implementation
+    }
+    sensor->UpdateConfig(temperature_control_checksum, this->name_checksum);
+    
     this->preset1 =             THEKERNEL->config->value(temperature_control_checksum, this->name_checksum, preset1_checksum)->by_default(0)->as_number();
     this->preset2 =             THEKERNEL->config->value(temperature_control_checksum, this->name_checksum, preset2_checksum)->by_default(0)->as_number();
 
index 751c684..874ae55 100644 (file)
@@ -11,7 +11,6 @@
 #include "Module.h"
 #include "Pwm.h"
 #include "TempSensor.h"
-#include <memory> // for auto_ptr
 
 class TemperatureControlPool;
 
@@ -19,6 +18,7 @@ class TemperatureControl : public Module {
 
     public:
         TemperatureControl(uint16_t name);
+        ~TemperatureControl();
 
         void on_module_loaded();
         void on_main_loop(void* argument);
@@ -35,9 +35,9 @@ class TemperatureControl : public Module {
         TemperatureControlPool *pool;
         friend class PID_Autotuner;
 
-               float get_temperature();
+        float get_temperature();
     private:
-               uint32_t thermistor_read_tick(uint32_t dummy);
+        uint32_t thermistor_read_tick(uint32_t dummy);
         void pid_process(float);
 
         float target_temperature;
@@ -45,8 +45,8 @@ class TemperatureControl : public Module {
         float preset1;
         float preset2;
 
-               std::auto_ptr<TempSensor> sensor;
-               
+        TempSensor *sensor;
+        
         // PID runtime
         float i_max;
 
@@ -54,7 +54,6 @@ class TemperatureControl : public Module {
 
         float last_reading;
 
-        float acceleration_factor;
         float readings_per_second;
 
         uint16_t name_checksum;
index 831c964..942a3d6 100644 (file)
@@ -74,7 +74,7 @@ void Thermistor::UpdateConfig(uint16_t module_checksum, uint16_t name_checksum)
 
 float Thermistor::get_temperature()
 {
-       return adc_value_to_temperature(new_thermistor_reading());
+    return adc_value_to_temperature(new_thermistor_reading());
 }
 
 float Thermistor::adc_value_to_temperature(int adc_value)
index e607d94..f5ce1cc 100644 (file)
 class Thermistor : public TempSensor
 {
     public:
-               Thermistor();
-               ~Thermistor();
-               
-               // TempSensor interface.
-               void UpdateConfig(uint16_t module_checksum, uint16_t name_checksum);
+        Thermistor();
+        ~Thermistor();
+        
+        // TempSensor interface.
+        void UpdateConfig(uint16_t module_checksum, uint16_t name_checksum);
         float get_temperature();
-               
+        
     private:
-               int new_thermistor_reading();
+        int new_thermistor_reading();
         float adc_value_to_temperature(int adc_value);
 
         // Thermistor computation settings
@@ -41,7 +41,7 @@ class Thermistor : public TempSensor
 
         RingBuffer<uint16_t,QUEUE_LEN> queue;  // Queue of readings
         uint16_t median_buffer[QUEUE_LEN];
-               
+        
 };
 
 #endif
index 338f3e1..3af0115 100644 (file)
 #define chip_select_checksum CHECKSUM("chip_select_pin")
 #define spi_channel_checksum CHECKSUM("spi_channel")
 
-Max31855::Max31855()
+Max31855::Max31855() :
+    spi(nullptr)
 {
 }
 
 Max31855::~Max31855()
 {
+    delete spi;
 }
 
 // Get configuration from the config file
 void Max31855::UpdateConfig(uint16_t module_checksum, uint16_t name_checksum)
 {
-       // Chip select
+    // Chip select
     this->spi_cs_pin.from_string(THEKERNEL->config->value(module_checksum, name_checksum, chip_select_checksum)->by_default("0.16")->as_string());
-       this->spi_cs_pin.set(true);
-       this->spi_cs_pin.as_output();
-       
+    this->spi_cs_pin.set(true);
+    this->spi_cs_pin.as_output();
+    
     // select which SPI channel to use
     int spi_channel = THEKERNEL->config->value(module_checksum, name_checksum, spi_channel_checksum)->by_default(0)->as_number();
     PinName miso;
     PinName mosi;
     PinName sclk;
     if(spi_channel == 0) {
-               // Channel 0
+        // Channel 0
         mosi=P0_18; miso=P0_17; sclk=P0_15;
     } else {
-               // Channel 1
+        // Channel 1
         mosi=P0_9; miso=P0_8; sclk=P0_7;
     } 
 
-       spi.reset(new SPI(mosi, miso, sclk));
+    delete spi;
+    spi = new mbed::SPI(mosi, miso, sclk);
 
-       // Spi settings: 1MHz (default), 16 bits, mode 0 (default)
-       spi->format(16);
+    // Spi settings: 1MHz (default), 16 bits, mode 0 (default)
+    spi->format(16);
 }
 
 float Max31855::get_temperature()
 {
-       this->spi_cs_pin.set(false);
-       wait_us(1); // Must wait for first bit valid
+       // Return an average of the last readings
+    if (readings.size() >= readings.capacity()) {
+        readings.delete_tail();
+    }
+
+       float temp = read_temp();
+
+       // Discard occasional errors...
+       if(!isinf(temp))
+       {
+               readings.push_back(temp);
+       }
+
+       if(readings.size()==0) return infinityf();
 
-       // Read 16 bits (writing something as well is required by the api)
-       uint16_t data = spi->write(0);
-//     Read next 16 bits (diagnostics)
+       float sum = 0;
+    for (int i=0; i<readings.size(); i++)
+        sum += *readings.get_ref(i);
+
+       return sum / readings.size();
+}
+
+float Max31855::read_temp()
+{
+    this->spi_cs_pin.set(false);
+    wait_us(1); // Must wait for first bit valid
+
+    // Read 16 bits (writing something as well is required by the api)
+    uint16_t data = spi->write(0);
+       //  Read next 16 bits (diagnostics)
 //     uint16_t data2 = spi->write(0);
 
-       this->spi_cs_pin.set(true);
-       
-       float temperature;
+    this->spi_cs_pin.set(true);
+    
+    float temperature;
 
     //Process temp
     if (data & 0x0001)
-       {
-               // Error flag.
+    {
+        // Error flag.
         temperature = infinityf();
-               // Todo: Interpret data2 for more diagnostics.
-       }
+        // Todo: Interpret data2 for more diagnostics.
+    }
     else
     {
         data = data >> 2;
@@ -86,5 +113,5 @@ float Max31855::get_temperature()
             temperature = ((data & 0x1FFF) + 1) / -4.f;
         }
     }
-    return temperature;        
+    return temperature; 
 }
\ No newline at end of file
index e3e16a5..9f85f3c 100644 (file)
 #include <string>
 #include <libs/Pin.h>
 #include <mbed.h>
-#include <memory>
+#include "RingBuffer.h"
 
 class Max31855 : public TempSensor
 {
 public:
-       Max31855();
-       ~Max31855();
-       void UpdateConfig(uint16_t module_checksum, uint16_t name_checksum);
-       float get_temperature();
+    Max31855();
+    ~Max31855();
+    void UpdateConfig(uint16_t module_checksum, uint16_t name_checksum);
+    float get_temperature();
 
 private:
-       Pin spi_cs_pin;
-       std::auto_ptr<mbed::SPI> spi;
+       float read_temp();
+    Pin spi_cs_pin;
+    mbed::SPI *spi;
+    RingBuffer<float,16> readings;
 };
 
 #endif