From a9f485549d196aceb95c78f0a7e6a14fbf26908f Mon Sep 17 00:00:00 2001
From: Jochen Vothknecht <jochen3120@gmail.com>
Date: Fri, 24 Nov 2023 23:17:06 +0100
Subject: [PATCH] Logging CJ-temperature now; Minor fixes & adjustments

---
 CLC-qthing/SiliconTorch/Hardware/MAX31856.cpp |  6 ++-
 CLC-qthing/SiliconTorch/Hardware/MAX31856.hpp |  1 +
 CLC-qthing/SiliconTorch/Service/BallMill.cpp  |  4 +-
 .../SiliconTorch/Service/SpiderFurnace.cpp    | 53 ++++++++++++++-----
 .../SiliconTorch/Service/SpiderFurnace.hpp    | 22 ++++++--
 CLC-qthing/SpiderLib/SlidingWindow.hpp        |  8 ++-
 6 files changed, 72 insertions(+), 22 deletions(-)

diff --git a/CLC-qthing/SiliconTorch/Hardware/MAX31856.cpp b/CLC-qthing/SiliconTorch/Hardware/MAX31856.cpp
index 5a60192..ac68799 100644
--- a/CLC-qthing/SiliconTorch/Hardware/MAX31856.cpp
+++ b/CLC-qthing/SiliconTorch/Hardware/MAX31856.cpp
@@ -60,7 +60,7 @@ namespace MAX31856 {
       sign   = -1.0f;
     }
 
-    return 0.0625f * regval * sign;
+    return 0.015625f * (regval >> 2) * sign;
   }
 
 
@@ -333,6 +333,10 @@ namespace MAX31856 {
     return tcreg2float(spi->readU24(LTCB::addr));
   }
 
+  f32 MAX31856::getCJTemperature() {
+    return cjreg2float(spi->readU16(CJT::addr));
+  }
+
 
 
   void MAX31856::setThermocoupleType(ThermocoupleType tc) {
diff --git a/CLC-qthing/SiliconTorch/Hardware/MAX31856.hpp b/CLC-qthing/SiliconTorch/Hardware/MAX31856.hpp
index 151fc8b..ec61cea 100644
--- a/CLC-qthing/SiliconTorch/Hardware/MAX31856.hpp
+++ b/CLC-qthing/SiliconTorch/Hardware/MAX31856.hpp
@@ -307,6 +307,7 @@ namespace MAX31856 {
 
 
       f32 getTemperature();
+      f32 getCJTemperature();
 
 
       void clearFaultBit();
diff --git a/CLC-qthing/SiliconTorch/Service/BallMill.cpp b/CLC-qthing/SiliconTorch/Service/BallMill.cpp
index 7c7adae..3ecdd11 100644
--- a/CLC-qthing/SiliconTorch/Service/BallMill.cpp
+++ b/CLC-qthing/SiliconTorch/Service/BallMill.cpp
@@ -79,8 +79,8 @@ namespace SiliconTorch {
             //  ch0->setDuty(0);
             //}
 
-            ch0->setFrqRes(_frq, 10);
-            ch0->setDuty(1 << (10 - 1));  // TODO: is setDutyFloat(0.5f) precise enough…?
+            ch0->setFrqRes(_frq, 8);
+            ch0->setDuty(1 << (8 - 1));  // TODO: is setDutyFloat(0.5f) precise enough…?
 
 
             if (abs(targetRPM - currentRPM) < CFG_RPM_CHANGE_PER_SECOND) {
diff --git a/CLC-qthing/SiliconTorch/Service/SpiderFurnace.cpp b/CLC-qthing/SiliconTorch/Service/SpiderFurnace.cpp
index a8c31a0..b974024 100644
--- a/CLC-qthing/SiliconTorch/Service/SpiderFurnace.cpp
+++ b/CLC-qthing/SiliconTorch/Service/SpiderFurnace.cpp
@@ -104,6 +104,11 @@ namespace SiliconTorch {
         ledc_channel_config(&ledc_channel);
 
 
+        // Configure fan PWM
+        fanPWM = new SimplePWM::SimplePWM(IO_FAN, LEDC_CHANNEL_6, 2);
+        fanPWM->setFrqRes(1000, 12);
+        setFanPWM(0.0f);
+
         // pre-seed sliding window
         f32 t = tc0->getTemperature();
         for (u8 n = 0; n < SlidingWindowLength; n++)
@@ -131,6 +136,7 @@ namespace SiliconTorch {
 
             if (!hasFault()) {
               f32 t = tc0->getTemperature();
+              tc0cjdat->insert(tc0->getCJTemperature());  // Read CJ sensor
 
               f32 deltaT = abs(t - temperature());
               //if (deltaT < 0) deltaT *= -1.0f;
@@ -151,7 +157,8 @@ namespace SiliconTorch {
               }
             }
 
-            f32 t = temperature();
+            f32 t   = temperature();
+            f32 cjt = coldJunctionTemperature();
 
             if (!hasFault() && t <= MAX_TEMP) {
 
@@ -172,9 +179,9 @@ namespace SiliconTorch {
               if (CFG_EN_PIDCTRL) setPWM(0.0f);
             }
 
-            ESP_LOGI(TAG, "T: % .3f °C    Fault: %s    _i: % .3f   _d: % .3f   PWM: % .3f", t, hasFault() ? "true" : "false", sum_error, diff_error, pwmVal);
+            ESP_LOGI(TAG, "T0: % .3f °C    CJT0: % .3f °C    Fault: %s    _i: % .3f   _d: % .3f   Heater0PWM: % .3f   Fan0PWM: % .3f", t, cjt, hasFault() ? "true" : "false", sum_error, diff_error, pwmVal, fanPWMVal);
 
-            if (cnt++ >= 10) {
+            if (cnt++ >= PUB_MEASURE_TICKS) {
 
               u64 timeMS = Time::ms();
               f32 _temp  = temperature();
@@ -188,19 +195,22 @@ namespace SiliconTorch {
 
               if (CFG_EN_LogMQTT) {
                 char tmp[256];
-                snprintf(tmp, sizeof(tmp), "[ % 8lld ]  T: % .3f °C    Fault: %s    _i: % .3f   _d: % .3f   PWM: % .3f   ΔT: % .3f K/s", Time::ms(), t, hasFault() ? "true" : "false", sum_error, diff_error, pwmVal, tempChangeRate);
+                snprintf(tmp, sizeof(tmp), "[ % 8lld ]  T0: % .3f °C    CJT0: % .3f °C    Fault: %s    _i: % .3f   _d: % .3f   Heater0PWM: % .3f   ΔT: % .3f K/s   Fan0PWM: % .3f", Time::ms(), t, cjt, hasFault() ? "true" : "false", sum_error, diff_error, pwmVal, tempChangeRate, fanPWMVal);
                 qthing::publish_message(deviceTopic(TAG, "log"), tmp);
               }
 
               json j;
-              j["_I"]      = sum_error;
-              j["_D"]      = diff_error;
-              j["ΔT"]      = tempChangeRate;
-              j["T"]       = temperature();
-              j["PWM"]     = pwmVal;
-              j["fault"]   = hasFault();
-              j["maxPWM"]  = std::min(MAX_PWM, maxPWM);
-              j["targetT"] = targetTemperature;
+              j["_I"]          = sum_error;
+              j["_D"]          = diff_error;
+              j["ΔT"]          = tempChangeRate;
+              j["T0"]          = t;
+              j["CJT0"]        = cjt;
+              j["Heater0PWM"]  = pwmVal;
+              j["Fan0PWM"]     = fanPWMVal;
+              j["fault"]       = hasFault();
+              j["maxPWM"]      = std::min(MAX_PWM, maxPWM);
+              j["targetT"]     = targetTemperature;
+              j["controlMode"] = "setT";  // or: rampT                                     // TODO: Make dynamic!!  (means implementing other states)
               qthing::publish_message(deviceTopic(TAG, "measure"), j.dump().c_str());
 
               cnt = 0;
@@ -261,7 +271,7 @@ namespace SiliconTorch {
               qthing::publish_message(deviceTopic(TAG, "temperature"), tmp);
             }
 
-            vTaskDelayUntil(&lastWakeTime, 420 / portTICK_PERIOD_MS);  // ~2 Hz
+            vTaskDelayUntil(&lastWakeTime, PUB_TEMPERATURE_MS / portTICK_PERIOD_MS);
           }
         });
 
@@ -284,6 +294,7 @@ namespace SiliconTorch {
         tc0["SCLK"]              = IO_SCLK;
         tc0["type"]              = "K";
         tc0["temperature"]       = t;
+        tc0["CJtemperature"]     = coldJunctionTemperature();
 
         out["tc0"]               = tc0;
         out["kP"]                = kP;
@@ -306,12 +317,28 @@ namespace SiliconTorch {
 
         ledc_set_duty(LEDC_HIGH_SPEED_MODE, pwmCh, pwmVal);
         ledc_update_duty(LEDC_HIGH_SPEED_MODE, pwmCh);
+
+        // simple fan regulation
+        if (value >= FAN_MIN_PWRON) setFanPWM(value * FAN_SCALING);
+        else                        setFanPWM(0.0f);
+      }
+
+      void SpiderFurnace::setFanPWM(f32 value) {
+        if (value < 0.0f) value = 0.0f;
+        if (value > 1.0f) value = 1.0f;
+
+        fanPWM->setDutyFloat(1.0f - value);
+        fanPWMVal = value;
       }
 
       f32 SpiderFurnace::temperature() const {
         return tc0dat->average();
       }
 
+      f32 SpiderFurnace::coldJunctionTemperature() const {
+        return tc0cjdat->average();
+      }
+
       bool SpiderFurnace::hasFault() const {
         return faultReg.value > 0;
       }
diff --git a/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp b/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp
index 6825582..9de8694 100644
--- a/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp
+++ b/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp
@@ -14,6 +14,7 @@
 #include <SpiderLib.hpp>
 #include "Service.hpp"
 #include "../Hardware/MAX31856.hpp"
+#include "../Hardware/SimplePWM.hpp"
 
 // qthing stuff
 #include "SiliconTorch/FxCyanRGB8.hpp"
@@ -29,16 +30,20 @@ namespace SiliconTorch {
 
     namespace SpiderFurnace {
 
-      constexpr u8  PWM_BITS               =    12;
-      constexpr u32 PWM_FREQ               =    69;       // Hz
+      constexpr u8  PWM_BITS               =    20;  // 12
+      constexpr u32 PWM_FREQ               =    13;  // 69       // Hz
       constexpr u8  TICK_FREQ              =    10;       // Hz
       constexpr u8  SlidingWindowLength    =     8;
       constexpr f32 MaxTempChangePerSecond =  1000.00f;   // K  // TODO: formally set to 100 but triggers too often?!
       constexpr f32 MAX_TEMP               =  1320.00f;   // °C
-      constexpr f32 MAX_PWM                =     0.67f;   // 0.70f  // p%
+      constexpr f32 MAX_PWM                =     0.70f;  // 0.65f with zero cross SSR  // 0.67f (with 69Hz PWM)   // 0.70f  // p%
       constexpr f32 DEFAULT_kP             =     0.02f;     // !!
       constexpr f32 DEFAULT_kI             =     0.000f;    // !!  // maybe 0.005f  ?
       constexpr f32 DEFAULT_kD             =     0.0000f;   // !!  // maybe 0.0025f ?
+      constexpr f32 FAN_SCALING            =     0.75f;      // Heater PWM duty will be multiplied by this to yield fan PWM duty
+      constexpr f32 FAN_MIN_PWRON          =     0.30f;      // min. Heater PWM duty at which the Fan will be engaged
+      constexpr u32 PUB_MEASURE_TICKS      =     5;         // period in PID-Ticks after which to publish measure-topic
+      constexpr u32 PUB_TEMPERATURE_MS     =  1000;         // period in ms after which to publish temperature-topic
 
       // TODO: Make configurable"
       constexpr u8  IO_CS                  =    26;
@@ -62,7 +67,7 @@ namespace SiliconTorch {
 
       // TODO: ???
       // Compile-time config
-      constexpr bool CFG_EN_LogMQTT             = true;
+      constexpr bool CFG_EN_LogMQTT             = false;
       constexpr bool CFG_EN_PIDCTRL             = true;
       constexpr bool CFG_EN_MQTT_PIDvals        = true;
       constexpr bool CFG_EN_LimitTempChangeRate = false;
@@ -84,6 +89,7 @@ namespace SiliconTorch {
           bool hasFault() const;
 
           f32 temperature() const;
+          f32 coldJunctionTemperature() const;
 
           void setTargetTemperature(f32 t);
 
@@ -111,7 +117,11 @@ namespace SiliconTorch {
 
           u64 tc0age = 0;  // ms
           MAX31856::MAX31856* tc0;
-          SlidingWindow<f32>* tc0dat = new SlidingWindow<f32>(SlidingWindowLength);
+          SlidingWindow<f32>* tc0dat   = new SlidingWindow<f32>(SlidingWindowLength);
+          SlidingWindow<f32>* tc0cjdat = new SlidingWindow<f32>(SlidingWindowLength);
+
+          f32 fanPWMVal = 0.0f;
+          SimplePWM::SimplePWM* fanPWM = NULL;
 
           SpiderLib::Util::LambdaTask* pidTask = NULL;
           SpiderLib::Util::LambdaTask* pubTask = NULL;
@@ -119,6 +129,8 @@ namespace SiliconTorch {
           f32 pwmVal = 0.0f;
           void setPWM(f32 value);
 
+          void setFanPWM(f32 value);
+
       };
 
 
diff --git a/CLC-qthing/SpiderLib/SlidingWindow.hpp b/CLC-qthing/SpiderLib/SlidingWindow.hpp
index 7339888..ffc7458 100644
--- a/CLC-qthing/SpiderLib/SlidingWindow.hpp
+++ b/CLC-qthing/SpiderLib/SlidingWindow.hpp
@@ -7,13 +7,14 @@ template <typename numerical_t>
 class SlidingWindow {
   public:
     SlidingWindow(u32 size);
+    ~SlidingWindow();
 
     numerical_t average();
     void insert(numerical_t value);
   private:
     u32 size;
     u32 current = 0;
-    numerical_t *values;
+    numerical_t* values;
 };
 
 
@@ -26,6 +27,11 @@ SlidingWindow<numerical_t>::SlidingWindow(u32 size) {
   for (u32 i = 0; i < size; i++) insert(0);
 }
 
+template <typename numerical_t>
+SlidingWindow<numerical_t>::~SlidingWindow() {
+  delete[] values;
+}
+
 template <typename numerical_t>
 void SlidingWindow<numerical_t>::insert(numerical_t value) {
   values[current++] = value;
-- 
GitLab