You are reading a single comment by @verdeimpacat and its replies. Click here to read the full conversation.
  • Updated code after extensive testing:

    var triac;
    var htu;
    var temp;
    var averageTemp;
    var humidity;
    var compHumidity;
    var targetTemp;
    var tempHistory = Float32Array(60); 
    function onInit () {
       I2C2.setup( {scl: B10, sda: B3, bitrate: 19200 } );
       htu = require('HTU21D').connect( I2C2 );
       // Before anything else we should turn off the triac
       triac=A8;
       digitalWrite(triac,0); //this shoud reset the pin and set it as output
       temp = (htu.readTemperature()+htu.readTemperatu­re()+htu.readTemperature())/3;
       //at power-on we assume the temperature was constant for the entire measurement history
       tempHistory.fill(temp);
       averageTemp = temp;
       //turn HTU21D heater on for two seconds just to make sure the HTU21D sensor
       //has no condensation
       htu.setHeaterOn( true );
       setTimeout('htu.setHeaterOn(false);', 2000);
       targetTemp = 8.00;
    }
           
    function pidControlLoop() {
       temp = (htu.readTemperature()+htu.readTemperatu­re()+htu.readTemperature())/3;
       humidity = htu.readHumidity();
       compHumdity = htu.getCompensatedHumidity( humidity, temp );
       var regulatedTemp = targetTemp;
       //we want to check that moving towards regulated temp does not produce 
       //condensation. Furthermore, if the current temp is close or bellow
       //dew point we wish to move to slightly higher temp
       var dewPointTemp=htu.getDewPoint(temp,compHu­mdity);
       if (((targetTemp-dewPointTemp) < 1) || ((temp - dewPointTemp) < 1)) {
          regulatedTemp=dewPointTemp + 1;
       }
       //same, we want to check that the oldest temperature measured was above the dew point temperature
       //this is needed to avoid condensation due to thermal inertia for glass or metal objects
       //we better move slowly to higher temperature if such.
       if ((tempHistory[59] - dewPointTemp) < 1) {
          regulatedTemp = tempHistory[59] + 1;
       }
       // here we apply the proportional-integrative-derivative control 
       var PIDresult =0.75 * (regulatedTemp-temp + 2 * (regulatedTemp-averageTemp) + 2 * (tempHistory[0]-temp));
       calculatedPWM  = E.clip (PIDresult, 0, 1);
       analogWrite(triac, calculatedPWM, { freq : 0.2 });
       //Prepare for the next loop
       averageTemp = averageTemp - (tempHistory[59] - temp)/60;
       for (i=59;i>0;i--) {
          tempHistory[i] = tempHistory[i-1];
       }
       tempHistory[0] = temp;
    }
    //power on initialization. Will be deleted if code saved in flash
    onInit();
    // hereby we set the control loop to 60 seconds
    setInterval('pidControlLoop()',60000);
    

    And few thoughts after the prototype build:

    • It is wiser to use a snuberless triac. It's even chipper and allows you to build the power control circuit without R4 and C1. That's good because you will want to keep the ac circuitry as simple as possible;
    • The triac needs a 6 cm x 4cm radiator. I trust the triac will not dissipate more than 10-15W, and due to the fact that it is triggered with the MOC3083 zero cross circuit, the heat is kept to a minimum. But since it is powered directly to the ac mains circuitry it's good to avoid any overheating, plastic melting or even worse - fire. After all the load is over 10A at 220V ac;

    The regulation precision is 0,15°C with the suited PID parameters but may easily move to +/- 1°C when the PID parameters are not adequate.

    No humans, animals or Espruino pico boards were hurt during this experiment, do not attempt to build this project if you are not familiar working with mains electricity and power electronics.

About