-
@Gordon:
What about upgading the design of Espruino WiFi board to move to more resources rich chip like STM32F413?
It's such a pitty that the new versions of Espruino drop functionalities just because of the memory limitations... -
-
-
-
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.readTemperature()+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.readTemperature()+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,compHumdity); 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.
- 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;
-
That's fair enough! As a matter of fact I was afraid that one would need to write the code in Assambler language to keep code delay to minimum. And it's fine that there is no hardware lock due to use in whatever board functionality of conflicting resources.
As for the speed in accessing data: there are plenty of applications like digital to analog audio conversion, bluetooth audio and possibly others where you won't need to store the data ( at least this is my assumption today ) but just to process it on the fly. -
Hi Gordon,
What are your thoughts about supporting I2S for audio digital on Espruino? I notice that the ST processor has such interfaces & features and I trust that nice application scenarios may arise from these (like enabling sound output, bluetooth audio, a.s.o.).
No particular project in my mind, just wondering if there are any hardware/software limitations for use. -
-
-
The testing over the weekend went fine and revealed several errors that are already corrected in the second version of the code published above.
Attached the image of the "test benchmark". It took three minutes to build ( half of the time because the LED was connected the other way around in the first instance) : )Meanwhile, all the prototype components arrived and I will move from software to electronics. It will take a while so... make no mistake, the project is not dropped!
PS: Really fast process working with an interpreter and not compiled code! -
-
-
Danke UliMerkel ! It is mentioned indeed!
Second pass over the code without any additional functionality but just with the advices of Gordon implemented.
Will use:
Espruino pico as controller
I2C1 for communication with HTU21D
IE: pin B7 I2C1 SDA .... DATA, pin B6 I2C1 SCL... CLOCK
triac control is connected via a MOC3083 optocoupler whoes LED is sourced via a resistor on pin A8var triac; I2C1.setup( {scl: B6, sda: B7, bitrate 56000 } ); var htu = require('HTU21D').connect( I2C1 ); var temp; var averageTemp; var humidity; var compHumidity; // improved accuracy for humidity var targetTemp; // for the finetuning of the regulation we will keep in TempHistory the // historical values of the last hour var tempHistory = Float32Array(60); function onInit () { // 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(); //at power-on we assume the temperature was constant for the last hour 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.50; } function pidControlLoop() { temp = htu.readTemperature(); 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 higher temp var dewPointTemp=htu.getDewPoint(temp,compHumdity); if (((targetTemp-dewPointTemp) < 1) || ((temp - dewPointTemp) < 1)) { regulatedTemp=dewPointTemp + 1; } //same, we want to check that the temperature one hour ago was above //the dew point temperature //this is because the metal and glass of the photo lenses has thermal //inertia and we don't want condensation to occur on these. 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 with some // coefficients we feel appropriate. We will make some temperature regulation // graphs to finetune these coefficients once the system is running var PIDresult =0.5 * (regulatedTemp-temp + 10 * (regulatedTemp-averageTemp) + 25 * (tempHistory[0]-temp)); //for summer days we should imagine vent./AC control if PIDresult is < zero... calculatedPWM = E.clip (PIDresult, 0, 1); analogWrite(triac, calculatedPWM, { freq : 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 onInit(); // hereby we set the control loop to 60 seconds setInterval('pidControlLoop()',60000);
My "mission" over the week-end: tweak the HTU21D module and define instead some sort of a function that reads the values of temperature and humidity from two potentiometers just to move forward with code debugging and triac control while awaiting for the prototype components.
Wish you will enjoy your weekend too ! -
Thanks Gordon!
Changing tempHistory instead of TempHistory will be easy. Understanding what a class is and how this could be used for my code will be postponed for my next project...
I am decided to follow your advice and I will revise the code as suggested and in the meantime further enhance it for functionalities and runtime efficiency.
For the moment I struggle to understand if onInit is a system function and if such why isn't it documented in the Espruino reference section. If it is not, what makes us sure that code defined inside onInit will be executed after power on? -
I received my first pico boards few days ago ( thank you Gordon, brilliant design from both software and hardware perspective!).
I started this temperature regulator project, mainly to have a start with Java Script which is unknown to me until now, but also with a real application in mind: as an amateur photographer I maintain a nice inventory of vintage cameras and lenses in a dependency of our house which is unheated over the winter.
Now, the design goals, adapted to this application are:
-maintain a low regulated temperature when I am not working, for the sake of decent electricity bill;
-maintain a comfortable temp whil I am spending time in that room;
-take care about the condensation and avoid rapid jumps in temperature when moving between the two;
Nice to have:
-remote control;
-temperature indication on some LCD or LEDs;
-Air Conditioning control for the summer days;
-some possibility to check for efficiency and status of control algorithm;
-real time clock to be able to program on a daily basis the target temperature;
I was not wise and I commited the aquisition of some components before having in mind the final design and thus I spend few good days trying hopelessly to write a HTU21D module... Christmas miracle: on December 22nd I found the just published HTU21D module on the Espruino site !!! Thank you Tom Gidden and Luwar !
Now, the code as of today ( functionality not checked yet since I am awaiting the prototype components):// Will use: //Espruino pico as controller //I2C1 for communication with HTU21D //IE: pin B7 I2C1 SDA .... DATA, pin B6 I2C1 SCL... CLOCK //triac control is connected via a MOC3083 optocoupler whoes LED is sourced via // a resistor on pin A8 // Before anything else we should turn off the triac var triac=A8; digitalWrite(triac,0); //this shoud reset the pin and set it as output I2C1.setup( {scl: B6, sda: B7, bitrate 50000 } ); var htu = require('HTU21D').connect( I2C1 ); //soft reset is required before use of HTU21D htu.softReset(); //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); var temp = htu.readTemperature(); var humidity = htu.readHumidity(); var CompHumidity = htu.getCompensatedHumidity( humidity, temp ); //returns improved accuracy for humidity var TargetTemp = 8.50; // this assumes 8.50°C as a perfect target for the scope of the regulation // for the finetuning of the regulation we will keep in TempHistory the // hystorical values of the last hour var TempHistory = Float32Array(60); // at power-on we assume the measured temperature was constant for the last hour TempHistory.fill(temp); var AverageTemp = temp; new function PWMregulation(t,CH) { 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 higher temp var DewPointTemp=htu.getDewPoint(t,CH); if ((TargetTemp-DewPointTemp) < 1) || ((t - DewPointTemp) < 1) { RegulatedTemp=DewPointTemp + 1; } //same, we want to check that the temperature one hour ago was above the //dew point temperature. This is because the metal and glass of the photolenses // has thermal inertia and we don't want condensation to occur on these. // We better move slowly to higher temperature if such. // Remember, the project aim is to protect photo gear & lenses against // condensation and resulting fungus ! if (TempHistory[59] - DewPointTemp) < 1 { RegulatedTemp = TempHistory[59] + 1; } //here we apply the proportional-integrative-derivative control with some // coeficients we feel appropriate. //we will make some temperature regulation graphs to finetune these coeficients // once the system is running var PIDresult =0.5*(RegulatedTemp-t + 10*(RegulatedTemp-AverageTemp) + 40*(TempHistory[0]-t)); var calculatedPWM = E.clip (PIDresult, 0, 1); return calculatedPWM; } // we set the control loop to 60 seconds // all planned activities for optimal regulation are executed inside the bellow loop setInterval( function() { temp = htu.readHumidity(); humidity = htu.readHumidity(); CompHumdity = htu.getCompensatedHumidity( humidity, temp ); analogWrite(triac, PWMregulation(temp,CompHumdity), { freq : 1 }); //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; },60000);
As you may notice the code is under construction and not all the design goals are fulfiled as of today. But I would welcome your thoughts on the approach, any errors I might have done sofar and ideas for code optimization.
-
Nice! Thanks! My mind is into it allready!