colinl / node-red-contrib-pid

A node-red PID loop controller node intended for the control of real world processes
Apache License 2.0
26 stars 17 forks source link

Derivative time as property type issue #26

Open kevintrewern opened 7 months ago

kevintrewern commented 7 months ago

Excuse my lack of node red experience.

I have used this PID controller within a subflow to add some reusability for my project (mainly coupling it with PWM). I was getting "Integral Locked" due to the process value being far from the setpoint - as expected - but this was dropping the output off so nothing ever happened (heating system). Eventually I realised that if I hard-coded the values into the PID node within my subflow, the output stays on as expected. After much experimentation, I found that the Derivative time was causing this if it was set to a number type. For now, setting it to a string type seems to fix this. Presumably these variables should all expect a number as standard?

Thanks, Kevin.

colinl commented 7 months ago

Yes, certainly it should work with numbers, I would be less surprised if you said it worked for numbers but not strings. I am not entirely certain I understand exactly what you have done, can you post some screenshots showing the config for the good and the bad case please. You can paste images directly here. Also please connect a debug node to the pid node output, set the debug node to output the complete message and show me what that gives for each case. Also please what version of the pid node, what version of node-red and what version of nodejs? node -v will tell you the nodejs version.

kevintrewern commented 7 months ago

PID PWM subflow This is the subflow

PID PWM subflow PID properties These are the properties of the PID within the subflow, inputs mapped to properties of the subflow

PID PWM subflow properties These are the properties of the subflow itself. If D_SET is changed from string to number then the PID will give an output of zero when it is Integral Locked and so nothing ever happens. If I change just D_SET to number then it will work, even with all the others set to number.

I did all the updates before I debugged this, so its v2.0.0. I don't know where to enter node-v in my setup. I am running Nodered in Home Assistant. Home Assistant is running within an ESXI server. I have been using it for years but don't get much time to play with it.

I don't understand how to use debug nodes. When I have tried all I see is millions of messages flashing past too quickly to read. Happy to do it if you can guide me. I am working away for the next few days but can try logging in remotely and having a go if you can point me in the right direction.

colinl commented 7 months ago

I see you have enable set to false, is that how you have it set normally? That should prevent the pid node from doing anything.

If D_SET is changed from string to number then the PID will give an output of zero when it is Integral Locked and so nothing ever happens. If I change just D_SET to number then it will work, even with all the others set to number.

I don't quite follow that. You say that it doesn't work with D_SET as a number, but then you say it does work with it as a number.

For the debug, add a Debug node to output 7 of the subflow. Set it to output the complete message:

image

Each time the node sends a message it will appear in the debug pane. To stop it sending to the debug pane you can click the button on the right hand end of the debug node, which will stop it sending, even without deploying again. Then you can click in the debug pane and expand the contents of the message to make it all visible.

Can you share the subflow itself? Configure one of the subflows so that it fails, then click that instance of it and, in the dropdown menu, select Export then Copy to Clipboard and paste it here between lines containing just three backticks, which will stop github from messing with the format. Like this

``` Paste it in here ```

Then I can test exactly your setup. It is a pity you are using HA, that makes it difficult sometimes to see what is going on, but it should not be a factor in the problem

kevintrewern commented 7 months ago

"If D_SET is changed from string to number then the PID will give an output of zero when it is Integral Locked and so nothing ever happens. If I change just D_SET to number then it will work, even with all the others set to number."

Should have read:

"If D_SET is changed from string to number then the PID will give an output of zero when it is Integral Locked and so nothing ever happens. If I change just D_SET to string then it will work, even with all the others set to number."

Being used to C, the fact that it can be a string or a number is odd enough to me but then as I said I haven't spent any proper time learning node-red.

Apologies for the confusion!

Yes I can certainly do those other things for you but I don't want to mess with it while I am away as it controls two of my boilers - I want to be around in case I mess it up lol!

The rooms that it controls only need heating ad-hoc - rooms that only I use when I am home, so I also have no need to switch them on while away either and with energy costing what it does....

colinl commented 7 months ago

I have tried to simulate the problem here, but I can't make it fail.

I don't want to mess with it while I am away as it controls two of my boilers - I want to be around in case I mess it up lol!

Absolutely.

kevintrewern commented 7 months ago

Thanks for trying, bear with me and when I get back home I will go through what you have asked. Strange that it works ok on one system and not another. Maybe its something odd about my installation. I will get back to you in a few days!

colinl commented 7 months ago

Any news on this? It would be good to get to the bottom of whatever is happening.

kevintrewern commented 7 months ago

Sorry, its been mad. I will take a look this weekend.

Cheers!

kevintrewern commented 7 months ago

This is the Debug with the POT setpoint at 30C as I am in there so already at ~21C. After setting everything to number type as you would expect it to be. (POT is nickname for the outbuilding).

POT Debug

kevintrewern commented 7 months ago

This is the Debug with the POT setpoint at 30C as I am in there so already at ~21C. After setting everything to string type. At this point thing start working normally.

POT NodeRed With all inputs and setpoints as string

kevintrewern commented 7 months ago

I tidied up the code a bit before I started the above tests, it is essentially the same just a bit easier for me to follow.

I have played with some different combinations of which variables are string and which are number.

D_SET does not seem to mind if it is a number or a string, contrary to what I said before. I_INIT must be a string. As soon as it isn't, once the PID hits integral lock, zero output.

This is with all the inputs on the subflow itself set to number type. I have repeated the same test with Conservatory which also uses the PID subflow and it behaves exactly the same. I have screenshots of the subflow and the UI. I can send them as well but they just show what you would expect, saying integral locked and zero output.

I am fairly sure that I wasn't even taking I_INIT as an input to the subflow when I originally got the problem - I added it to eliminate a possible issue with it not being set! So I am now concerned that there is a consistency issue, or I reported the wrong variable in my haste!

I don't know what to suggest from here. Both POT and Conservatory are working perfectly with I_INIT set to string and everything else set to number. That is also with all the subflow inputs set to type number!

I hope I have explained this properly, I find it hard to describe!

Thanks!

colinl commented 7 months ago

This is the Debug with the POT setpoint at 30C as I am in there so already at ~21C. After setting everything to string type. At this point thing start working normally.

It isn't working as it should, in particular: image

The integral term is Not a Number (NaN) which means something is not right.

I can manage to make things fail if I I have parameters set to String type in the subflow settings. This is due to the fact that it is possible to enter invalid values into fields. When you configure a PID node not in a subflow then there is validity checking to make sure that only numbers can be entered into number fields, so for example if you try to put blabla into the Initial Integral field it flags it as a config error. When the node is used in a subflow then the validity checking in the node config is bypassed so it is possible to enter invalid values. However, the symptom you are seeing is that it fails if the values are entered as number types, which doesn't make sense to me at the moment.

I have just noticed that you have Initial Integral set to 86400. It should be a value between 0 and 1, it being the power output on startup if the PV is on the SP. That should not give NaN though.

If I were to create a version of the PID node that outputs additional debug would you be prepared to install it (that is very easy) so that I can work out what is going on?

kevintrewern commented 7 months ago

I understand what you are saying about the types. If it bypasses the checks and its not a number then that would make perfect sense to give problems but to get the problem when you set it specifically to a number so it cannot be anything else obviously doesn't!

Yes the NaN jumped straight out at me! I wasn't sure what a good initial value was and used the input value but that's in seconds so obviously not the same thing. Its just a default though (I assume) as I set it when I use the subflow to zero though I have now changed that to 0.5 in usage and the subflow as well, as it seems to be more reasonable? Again pretty sure I had this set to zero when I initially had the issue so I doubt that its related and you would know best if you say it wont be :)

Yes I can give your debug version a run. so you can get more debug feedback, that's no problem!

I have an increasing feeling this is a problem with the Home Assistant environment and quite possibly some unique error my install has picked up along the years of updates.

Kev.

colinl commented 7 months ago

I don't think it is likely to be an HA issue, this should not be interacting with HA at all. You are right that the large value in initial integral should not cause the problems you are seeing, it would just make it slow to home in on the setpoint initially. I have created a debug version. Having said it would be easy to install I had forgotten you were running in HA, but hopefully that is not a big problem. In HA is node-red running in a docker container? If so then you will need to open a shell in the container and cd into the folder where the flows file is, I will do some googling for you if you don't know how to do that. Once in there run npm list node-red-contrib-pid which should say something like └── node-red-contrib-pid@2.0.0 which confirms you are in the right place. Then run npm install colinl/node-red-contrib-pid#param_debug_branch which will install the new version. There might be a complication there, I don't know whether it is necessary to have git installed in the container to do the install, if it complains that git is not installed then come back and I will see if I can work out how to do that in HA

Assuming it went ok then restart node-red. If the install failed then it should not have changed anything so it should keep working as before, without restarting node-red.

Then the debug node on the output should show the params. Make sure you click the objects in the debug pane so they all get expanded, then you should see something like

image

colinl commented 7 months ago

Having done a bit of searching, then unfortunately I don't know if it even possible to install a branch version of the node when running in HA, so this may be a dead end.

colinl commented 7 months ago

Do you install node-red-contrib-pid under Option: npm packages as described here? If so then try using colinl/node-red-contrib-pid#param_debug_branch as the package name, and include git under Option: system_packages

kevintrewern commented 7 months ago

It was originally a vm in .ods format I think, which I imported into ESXI. It runs its own OS (HAOS). Yes it is installed under add-ons. HA has changed quite a bit since I originally installed it. I remember it breaking and having to fiddle about to fix it, couldn't tell you what I did to get it running now but it was basically stuck where several packages wouldn't update then I got some to update and it broke some others and so on. Everything has been working for over a year now. I generally find it surprisingly stable considering the amount of updates that happen. I don't work on it much, time is tight, so I just use what I have and don't change it very much other than updates.

These are the configuration options for the add-on, and below that, the PID package installed in Node Red, could you explain where I should put the above?

Config PID install

colinl commented 7 months ago

What is in the dropdowns system_packages and npm_packages?

kevintrewern commented 7 months ago

Nothing, they are empty!

colinl commented 7 months ago

How did you tell it to install node-red-contrib-pid?

kevintrewern commented 7 months ago

I believe I installed using Manage Palette | Install.

I don't know of any other way though I installed is a long time ago now.

colinl commented 7 months ago

OK, sorry, I am well outside my knowledge base on HA, so maybe we can't install the debug version.

Lets try a different tack. Could you configure one of your instances so that it is failing then select it, Export it and paste it here please, so I can see if it fails for me.

kevintrewern commented 7 months ago

Hi,

I was visiting family yesterday so I just got to this now.

OK so this is what happened today:

1) Conservatory is cold so I went to use this flow to get you your requested exported flow. 2) Changed I_INIT in the main flow to string type (everything else is already a number type including I_INIT in the subflow). 3) Took a screenshot of the flow running before it went into integral lock. 4) Took another screenshot once the flow had entered integral lock. 5) Double checked before exporting the flow, and the output was still on!! 6) Switched the system off and on (its just an enable flag from HA to enable the heating in that room), still working perfectly! 7) Turned up the setpoint in POT, switched I_INIT to number type in that, waited for integral lock, again, output remained on!

I don't know what else to say really! Clearly and as I had started to suspect before, there is some inconsistency - at least in my installation. I had narrowed it down to I_INIT on the main flow and double checked that last time I worked on this with you. Indeed that is why everything else is already set to number type! Also bearing in mind that I am pretty sure that I previously narrowed it down to SET_D, something odd is happening.

I did install all the updates after working on it the other day - Home assistant, Home assistant core and each of the nodes in the palette of Node-red. This broke the integration with HA ironically and I had to manually re-add the home assistant server node - just after I had told you that I never have problems with updates breaking things!

It doesn't look like there is anything you can do since it is now quite happily working with all the types set to number.

I am sorry this has taken up your time and a bit annoyed that it has also taken up (rather a lot) mine!

I feel like I am missing something but cant see what it could be, it just seems like its inconsistent.

Kevin.

colinl commented 6 months ago

To check everything is working ok, look in the debug output and check you do not see NaN for anything. Investigating you problem has shown up that I could do better checks on some parameters (particularly initial integral) to make sure they are actually numbers. The NaN probably indicates that one or more parameters had non-numeric characters in them. What is difficult to understand is exactly how this was happening in your case.

kevintrewern commented 6 months ago

OK, all looks normal to me?

image

colinl commented 6 months ago

It is a bit unusual that the integral term is zero, but that may just be that you have only just started it up.

kevintrewern commented 6 months ago

Ill let it run for a while and see if it changes. I know POT does when its not locked at least.

kevintrewern commented 6 months ago

Same - isn't it because its PID locked?

image

Here is POT when up to temperature:

image

colinl commented 6 months ago

Same - isn't it because its PID locked?

Yes, and I guess you have initial integral set to 0. Once the loops starts working then the integral term should start to take control.

kevintrewern commented 6 months ago

No, I have it set to 0.5!

image

colinl commented 6 months ago

The important thing is that the integral starts doing something when the process gets near the setpoint and the pid starts working.

kevintrewern commented 6 months ago

It always seems to work when its not integral locked. The issue was if it wanted to integral lock it would not bring the output on so I think its very likely working fine. The only check I haven't done is check it now that it is working using everything as a number, from cold, as I already had the POT heated up and the Conservatory doesn't need heating right now. I will find that out tomorrow and report back.

colinl commented 6 months ago

Nothing to do with the problem with NaN that you have been having, but I am dubious about your derivative time of 200, that is a large derivative for an integral of 600, especially with a sample rate of 2 minutes (if I read the debug correctly). To make derivative work reliably at 200 seconds you would need a sample rate of about 20 seconds. Do you not get large variations in power output from sample to sample with it at 300? In fact even for the integral at 600 I would advise a sample rate of 60 seconds or faster. Looking at your flow image, have you got smoothing on the temperature input? If you added that to reduce fluctuations then I think you might be better to take the smoothing out and remove the derivative (set it at zero). If possible sample the temperature at 1 minute intervals or faster. I think you may find that gives you a smoother power output and control just as good or better.

kevintrewern commented 6 months ago

Thanks - I value your advice on configuration of the PID loop!

The update rate for the process variable is set to something like 20s. I dint recall exactly and not at machine right now. When I configured the loop initially it was 1s (I am used to regulating things like flow rates on pumps with PID loops so I struggle working with stuff that reacts so very slowly!).

I found the reading ( process valie) very reactive since there is no smoothing built in so I added the smoothing to cater for draughts from entering the room, walking past the sensor etc.

I have found it fairly stable. It does overshoot the first time it gets to temperature which isn't surprising when the heat source is a gas boiler which builds up a core heat when running for a long while and then continues to dissipate the heat in its overrun mode. I have actually found this works fine for me as the building fabric is cold in the start up scenario which to me makes it feel colder than it actually is in the air so an initial boost helps to overcome that.

Always open to suggestions though so if you have further comments I would live to hear them!

I have found it challenging and time consuming dialling it in, its so different from a highly reactive load such as a pump on an invertor or a modulating valve! As I mention above its both slow to react and the boiler gives different responses depending on when it last fired. Electric heating would be much easier, I am sure!

colinl commented 6 months ago

Do you use something that allows you to keep a record of the response with different settings? I use influxdb and grafana. That allows me to go back and compare the response with different settings. Yes it can be frustrating, the fact that you may have to wait for hours for things to stabilise. Are you using hot water radiators for the heating?

kevintrewern commented 6 months ago

I have Grafana and Influxdb setup on HA. I'm ot sure if it's recording the PID setpoints though. I will get onto that later.

Yes, hot water radiators. On the POT its a system with about 7 rads, 2 in the main room where the stat is and those TRVs wide open. Other rooms have TRVs set conservatively as usually not used, POT doors always closed.

On the Conservatory that it a split system (S plan I think it's called). So on that, my control system opens an EAV which has a boiler call connected to its open limit. That circuit has 2 other rads set fairly low on their TRVs. And the main one with the TRV wide open. The other circuit does another 7 rads controlled by a separate (wife friendly!) System - Schnieder/wiser. Connected to the second EAV with boiler call also on its open limit.

So, nothing very stable in either setup. I am realistic in my expectations! I just didn't want to have a simple switch with massive overshoots all the time and I like PID loops! I also like overcomplicated my daily life!!!

kevintrewern commented 6 months ago

image

colinl commented 6 months ago

I can't work out what that is showing. For tuning, what I like to see is the power output from the PID (the payload) and the temperature. That is for a fixed setpoint obviously.

kevintrewern commented 6 months ago

image

colinl commented 6 months ago

As you can see, the output is all over the place. I suggest you start by setting the derivative time to 0 (for the moment) and set the integral time to 30 minutes (1800) and see what happens. I got the 30 mins by looking at the previous chart which seems to suggest a period of about 50 minutes or an hour. If you still have smoothing on the temperature then take that off too, for the moment.

kevintrewern commented 6 months ago

OK That is done for POT and Cons which are both currently on. Changes were made around 15:15. Will see what gets logged. Obviously these are not a cold start but it will be interesting to see how it regulates now.

Here is the graph up to this point. I have no idea why the current outputs of zero have not been plotted. I could do with spending a few hours learning how to use Grafana really!

image

kevintrewern commented 6 months ago

OK so no heating got called - I got cold and checked up on it! P output went to NaN! If I add smoothing back in, it works again! For now, I have set smoothing to 1 sample so that the PID runs but there is no actual smoothing taking place.

Weird.

colinl commented 6 months ago

What is the difference between no smoothing and smoothing set to 1? Was it the input to the pid node that went to NaN?

colinl commented 6 months ago

Perhaps I misunderstand what you mean by smoothing. Are you talking about smoothing outside the pid node, or the smoothing built into the node (which only affects derivative)

kevintrewern commented 6 months ago

Smooth is set to mean and it was set to 10 samples that the mean is taken from, I have set it to 1 to effectively disable smoothing.

Sorry, I think I forgot to wait for Integral lock before as it was so slow to get into it due to temperature interval being 30...

Still no heating with NaN!

I have set the update interval of the temperature to 1 (was 15 this morning then 30 when I changed the other PID settings earlier). I have only set it to 1 as it makes the PID go into integral lock much quicker so enables me to test it in good time.

I have now eliminated smoothing, that was not the problem. I have managed to get it working again without smoothing. I had to set D_Set to string type!

image

colinl commented 6 months ago

If you can get it so that anything coming out is showing NaN then select that instance of the subflow, Export it, and paste it here. Then I can have a look at it.

kevintrewern commented 6 months ago

POT seems to have stabilised though will have to see if it can get to setpoint from a cold start tomorrow.

image

kevintrewern commented 6 months ago

If you can get it so that anything coming out is showing NaN then select that instance of the subflow, Export it, and paste it here. Then I can have a look at it.

I am not changing the subflow, only the parameters that are passed to it, so POT and CONS are using the same subflow, and I can break them individually by setting D_SET to a string in either the POT or the CONS flow. I will see if I can get CONS and subflow for you now as CONS is still calling hard (its struggling to catch up with all the wind on all the windows in there).

kevintrewern commented 6 months ago

Here it is...

Settings before code copied: image

CONS flow:

[{"id":"c5b37bdc.62ddc","type":"subflow","name":"PID PWM","info":"","category":"","in":[{"x":40,"y":260,"wires":[{"id":"57f96543.f90014"},{"id":"0d9b4bdf5390b3fa"}]}],"out":[{"x":1300,"y":100,"wires":[{"id":"ced7cf25.1a82c","port":0}]},{"x":1300,"y":160,"wires":[{"id":"ced7cf25.1a82c","port":1}]},{"x":1290,"y":240,"wires":[{"id":"f2327bd2.e4f88","port":0}]},{"x":1300,"y":300,"wires":[{"id":"60e50ce7.969a94","port":0}]},{"x":1300,"y":380,"wires":[{"id":"184f4b15e7537d74","port":0}]},{"x":1300,"y":40,"wires":[{"id":"3740c0e.02273c","port":0}]},{"x":600,"y":200,"wires":[{"id":"57f96543.f90014","port":0}]},{"x":850,"y":460,"wires":[{"id":"57f96543.f90014","port":0}]}],"env":[{"name":"SETPOINT","type":"num","value":"20"},{"name":"P_SET","type":"num","value":"1.4"},{"name":"I_SET","type":"num","value":"86400"},{"name":"D_SET","type":"num","value":"0"},{"name":"I_INIT","type":"num","value":"0.5"},{"name":"MAX_SAMP_INT","type":"num","value":"1200"},{"name":"D_SMOOTH","type":"num","value":"0"},{"name":"ENABLE","type":"bool","value":"false"},{"name":"OUT_POW_WHEN_DIS","type":"num","value":"0"}],"meta":{"module":"PID PWM","version":"1.0.0","desc":"PID with PWM developed for boiler heating"},"color":"#E9967A","inputLabels":["input"],"outputLabels":["switch_on","switch_off","duty_s","duty_%","PID_%","duty_call","PID_output_raw","PID_output"],"status":{"x":660,"y":520,"wires":[{"id":"b68243a88e7c3da2","port":0}]}},{"id":"f1a5fc43.3c97d","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0.249","maxout":"1","action":"scale","round":false,"property":"payload","name":"Upper 75% prop","x":600,"y":280,"wires":[[]]},{"id":"3740c0e.02273c","type":"timeprop","z":"c5b37bdc.62ddc","name":"PWM","cycleTime":"300","deadTime":"30","triggerPeriod":"10","invert":false,"x":970,"y":140,"wires":[["ced7cf25.1a82c"]]},{"id":"ced7cf25.1a82c","type":"switch","z":"c5b37bdc.62ddc","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1150,"y":140,"wires":[[],[]]},{"id":"f2327bd2.e4f88","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0","maxout":"300","action":"scale","round":true,"property":"payload","name":"Duty (s)","x":1100,"y":240,"wires":[[]]},{"id":"60e50ce7.969a94","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0","maxout":"100","action":"scale","round":true,"property":"payload","name":"Duty (%)","x":1100,"y":300,"wires":[[]]},{"id":"57f96543.f90014","type":"PID","z":"c5b37bdc.62ddc","name":"PID","setpoint":"${SETPOINT}","pb":"${P_SET}","ti":"${I_SET}","td":"${D_SET}","integral_default":"${I_INIT}","smooth_factor":"${D_SMOOTH}","max_interval":"${MAX_SAMP_INT}","enable":"${ENABLE}","disabled_op":"${OUT_POW_WHEN_DIS}","x":350,"y":260,"wires":[["2c949416e55c666c","6bd50dcf.510a2c"]]},{"id":"6bd50dcf.510a2c","type":"function","z":"c5b37bdc.62ddc","name":"under 10% cutoff","func":"var payload = msg.payload\nif(payload < 0.10)\n    {\n        payload = 0\n    }\nmsg.payload = payload \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":260,"wires":[["60e50ce7.969a94","f2327bd2.e4f88","3740c0e.02273c"]]},{"id":"2c949416e55c666c","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0","maxout":"100","action":"scale","round":false,"property":"payload","name":"PID Duty (%)","x":590,"y":380,"wires":[["184f4b15e7537d74"]]},{"id":"b68243a88e7c3da2","type":"status","z":"c5b37bdc.62ddc","name":"","scope":null,"x":500,"y":520,"wires":[[]]},{"id":"184f4b15e7537d74","type":"change","z":"c5b37bdc.62ddc","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"op","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":380,"wires":[[]]},{"id":"0d9b4bdf5390b3fa","type":"function","z":"c5b37bdc.62ddc","name":"on/off mode","func":"if (msg.payload < 20.0) { msg.payload = true; } else { msg.payload = false;}\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":60,"wires":[[]]},{"id":"b664267a.c56958","type":"tab","label":"Cons Heating","disabled":false,"info":""},{"id":"e61977f.737b708","type":"api-current-state","z":"b664267a.c56958","name":"Cons Check Off","server":"233f608c.720b3","version":3,"outputs":2,"halt_if":"true","halt_if_type":"bool","halt_if_compare":"is","entity_id":"switch.conszone","state_type":"habool","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":1060,"y":140,"wires":[["dfddaebd.1d5488"],[]]},{"id":"126d6d6f.f2c4e3","type":"api-current-state","z":"b664267a.c56958","name":"Cons Check On","server":"233f608c.720b3","version":3,"outputs":2,"halt_if":"false","halt_if_type":"bool","halt_if_compare":"is","entity_id":"switch.conszone","state_type":"habool","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":1060,"y":80,"wires":[["192021.5a8f97e"],[]]},{"id":"c2c1e628.907dd","type":"ui_gauge","z":"b664267a.c56958","name":"Cons Duty (%)","group":"625a03d2.fac744","order":1,"width":0,"height":0,"gtype":"gage","title":"Duty (%)","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":1060,"y":260,"wires":[]},{"id":"79704fa6.8f0b1","type":"ui_gauge","z":"b664267a.c56958","name":"Cons Duty (s)","group":"625a03d2.fac744","order":2,"width":0,"height":0,"gtype":"gage","title":"Duty (s)","label":"s","format":"{{value}}","min":0,"max":"300","colors":["#ffb3b3","#ff6464","#ff0000"],"seg1":"150","seg2":"450","diff":false,"className":"","x":1060,"y":200,"wires":[]},{"id":"d114c595.c4658","type":"ui_gauge","z":"b664267a.c56958","name":"Cons Setpoint","group":"b790fcb.29c628","order":1,"width":0,"height":0,"gtype":"gage","title":"Setpoint","label":"°C","format":"{{value}}","min":"5","max":"30","colors":["#80ff80","#80ff80","#ff0000"],"seg1":"","seg2":"","diff":false,"className":"","x":460,"y":340,"wires":[]},{"id":"83372335.f9dbb8","type":"ui_switch","z":"b664267a.c56958","name":"","label":"Boiler Call","tooltip":"","group":"b790fcb.29c628","order":4,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","topicType":"str","style":"","onvalue":"1","onvalueType":"num","onicon":"","oncolor":"","offvalue":"0","offvalueType":"num","officon":"","offcolor":"","animate":true,"className":"","x":1050,"y":20,"wires":[[]]},{"id":"dfddaebd.1d5488","type":"api-call-service","z":"b664267a.c56958","name":"Cons Boiler Off","server":"233f608c.720b3","version":5,"debugenabled":true,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.conszone"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","output_location":"","output_location_type":"none","x":1260,"y":140,"wires":[[]]},{"id":"192021.5a8f97e","type":"api-call-service","z":"b664267a.c56958","name":"Cons Boiler On","server":"233f608c.720b3","version":5,"debugenabled":true,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.conszone"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","output_location":"","output_location_type":"none","x":1260,"y":80,"wires":[[]]},{"id":"302e5c0a.0ab83c","type":"poll-state","z":"b664267a.c56958","name":"sensor.consstat_bme280_temperature","server":"233f608c.720b3","version":3,"exposeAsEntityConfig":"","updateInterval":"30","updateIntervalType":"num","updateIntervalUnits":"seconds","outputInitially":true,"outputOnChanged":true,"entityId":"sensor.consstat_bme280_temperature","stateType":"num","ifState":"","ifStateType":"str","ifStateOperator":"is","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":170,"y":280,"wires":[["3bbde4eb.ec2894","a97d48ca4f88a374","4b0b7924.e0ce38"]]},{"id":"c484621b.28a1f8","type":"change","z":"b664267a.c56958","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"enable","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":160,"wires":[["4b0b7924.e0ce38"]]},{"id":"6eab321c.c98c24","type":"server-state-changed","z":"b664267a.c56958","name":"input_number.var_setpoint_heating_cons","server":"233f608c.720b3","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"input_number.var_setpoint_heating_cons","entityIdType":"exact","outputInitially":true,"stateType":"num","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":180,"y":220,"wires":[["b9a4e326.66f5","d114c595.c4658"]]},{"id":"b9a4e326.66f5","type":"change","z":"b664267a.c56958","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"setpoint","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":220,"wires":[["4b0b7924.e0ce38"]]},{"id":"3bbde4eb.ec2894","type":"ui_gauge","z":"b664267a.c56958","name":"Cons Temperature","group":"b790fcb.29c628","order":2,"width":0,"height":0,"gtype":"gage","title":"Temperature","label":"°C","format":"{{value}}","min":"5","max":"30","colors":["#00ffff","#80ff80","#ff0000"],"seg1":"18","seg2":"23","diff":false,"className":"","x":450,"y":400,"wires":[]},{"id":"44fb632f.5b46e4","type":"ui_text","z":"b664267a.c56958","group":"625a03d2.fac744","order":4,"width":0,"height":0,"name":"Cons I Current Value","label":"I Current Value","format":"{{msg.integral}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":"","color":"#000000","x":1080,"y":500,"wires":[]},{"id":"fd4c1831.46b6b","type":"ui_text","z":"b664267a.c56958","group":"625a03d2.fac744","order":5,"width":0,"height":0,"name":"Cons D Current Value","label":"D Current Value","format":"{{msg.derivative}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":"","color":"#000000","x":1080,"y":540,"wires":[]},{"id":"22a17f22.b05088","type":"ui_text","z":"b664267a.c56958","group":"625a03d2.fac744","order":3,"width":0,"height":0,"name":"Cons P Current Value","label":"P Current Value","format":"{{msg.proportional}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":"","color":"#000000","x":1080,"y":460,"wires":[]},{"id":"4b0b7924.e0ce38","type":"subflow:c5b37bdc.62ddc","z":"b664267a.c56958","name":"Cons PID","env":[{"name":"P_SET","value":"1.5","type":"num"},{"name":"I_SET","value":"1800","type":"num"},{"name":"D_SMOOTH","value":"5","type":"num"},{"name":"P","value":"8","type":"num"},{"name":"I","value":"30","type":"num"},{"name":"D","value":"15","type":"num"}],"x":720,"y":200,"wires":[["126d6d6f.f2c4e3"],["e61977f.737b708"],["79704fa6.8f0b1","7ed9f2146c9c1de5"],["c2c1e628.907dd","56e8b2f92d264137"],["769cf9e8.a45b78"],["83372335.f9dbb8"],["4b06d485d777a72d","22a17f22.b05088","44fb632f.5b46e4","fd4c1831.46b6b","87cb4190056bc6a8"],["abfd24b4d6bd83bb"]]},{"id":"769cf9e8.a45b78","type":"ui_text","z":"b664267a.c56958","group":"625a03d2.fac744","order":7,"width":0,"height":0,"name":"Cons PID % Value","label":"PID % Value","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":"","color":"#000000","x":1070,"y":420,"wires":[]},{"id":"759145dcfd72049f","type":"server-state-changed","z":"b664267a.c56958","name":"input_boolean.var_enable_heating_cons","server":"233f608c.720b3","version":5,"outputs":1,"exposeAsEntityConfig":"","entityId":"input_boolean.var_enable_heating_cons","entityIdType":"exact","outputInitially":true,"stateType":"habool","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":180,"y":160,"wires":[["c484621b.28a1f8"]]},{"id":"4b06d485d777a72d","type":"ha-sensor","z":"b664267a.c56958","name":"cons_heating_pid.proportional","entityConfig":"c016d6db.f544e8","version":0,"state":"msg.proportional","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1110,"y":320,"wires":[["cd199b93f8e2882c"]]},{"id":"7ed9f2146c9c1de5","type":"ha-sensor","z":"b664267a.c56958","name":"cons_heating_pid.duty_sec","entityConfig":"e3cd0e1f.810fb","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1300,"y":200,"wires":[[]]},{"id":"56e8b2f92d264137","type":"ha-sensor","z":"b664267a.c56958","name":"cons_heating_pid.duty_perc","entityConfig":"a8c71251.de1fe","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1300,"y":260,"wires":[[]]},{"id":"cd199b93f8e2882c","type":"ha-sensor","z":"b664267a.c56958","name":"cons_heating_pid.integral","entityConfig":"d459b977.4e1438","version":0,"state":"msg.integral","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1370,"y":320,"wires":[["5d25ea8c1eda8ba2"]]},{"id":"5d25ea8c1eda8ba2","type":"ha-sensor","z":"b664267a.c56958","name":"cons_heating_pid.derivative","entityConfig":"324c01b7.769426","version":0,"state":"msg.derivative","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1620,"y":320,"wires":[[]]},{"id":"87cb4190056bc6a8","type":"debug","z":"b664267a.c56958","name":"Cons Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1050,"y":380,"wires":[]},{"id":"a97d48ca4f88a374","type":"smooth","z":"b664267a.c56958","name":"","property":"payload","action":"mean","count":"1","round":"2","mult":"single","reduce":true,"x":480,"y":460,"wires":[["50bef3f58e396c1b"]]},{"id":"50bef3f58e396c1b","type":"ui_gauge","z":"b664267a.c56958","name":"Cons Temperature Smoothed","group":"b790fcb.29c628","order":3,"width":0,"height":0,"gtype":"gage","title":"Temperature Smoothed","label":"°C","format":"{{value}}","min":"5","max":"30","colors":["#00ffff","#80ff80","#ff0000"],"seg1":"18","seg2":"23","diff":false,"className":"","x":720,"y":460,"wires":[]},{"id":"abfd24b4d6bd83bb","type":"ui_text","z":"b664267a.c56958","group":"625a03d2.fac744","order":6,"width":0,"height":0,"name":"Cons PID Output","label":"PID Output","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":"","color":"#000000","x":1070,"y":580,"wires":[]},{"id":"233f608c.720b3","type":"server","name":"Home Assistant","version":5,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"625a03d2.fac744","type":"ui_group","name":"Cons Heating Tuning","tab":"99074dd0.4271e8","order":4,"disp":true,"width":"6","collapse":false},{"id":"b790fcb.29c628","type":"ui_group","name":"Cons Heating","tab":"99074dd0.4271e8","order":3,"disp":true,"width":"6","collapse":false},{"id":"c016d6db.f544e8","type":"ha-entity-config","server":"233f608c.720b3","deviceConfig":"","name":"sensor config for cons_heating_pid.proportional","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"cons_heating_pid.proportional"},{"property":"device_class","value":"status"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"P"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"e3cd0e1f.810fb","type":"ha-entity-config","server":"233f608c.720b3","deviceConfig":"","name":"sensor config for cons_heating_pid.duty_sec","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"cons_heating_pid.duty_sec"},{"property":"device_class","value":"status"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"s"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"a8c71251.de1fe","type":"ha-entity-config","server":"233f608c.720b3","deviceConfig":"","name":"sensor config for cons_heating_pid.duty_perc","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"cons_heating_pid.duty_perc"},{"property":"device_class","value":"status"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"d459b977.4e1438","type":"ha-entity-config","server":"233f608c.720b3","deviceConfig":"","name":"sensor config for cons_heating_pid.integral","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"cons_heating_pid.integral"},{"property":"device_class","value":"status"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"I"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"324c01b7.769426","type":"ha-entity-config","server":"233f608c.720b3","deviceConfig":"","name":"sensor config for cons_heating_pid.derivative","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"cons_heating_pid.derivative"},{"property":"device_class","value":"status"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"D"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"99074dd0.4271e8","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

PID Subflow

[{"id":"c5b37bdc.62ddc","type":"subflow","name":"PID PWM","info":"","category":"","in":[{"x":40,"y":260,"wires":[{"id":"57f96543.f90014"},{"id":"0d9b4bdf5390b3fa"}]}],"out":[{"x":1300,"y":100,"wires":[{"id":"ced7cf25.1a82c","port":0}]},{"x":1300,"y":160,"wires":[{"id":"ced7cf25.1a82c","port":1}]},{"x":1290,"y":240,"wires":[{"id":"f2327bd2.e4f88","port":0}]},{"x":1300,"y":300,"wires":[{"id":"60e50ce7.969a94","port":0}]},{"x":1300,"y":380,"wires":[{"id":"184f4b15e7537d74","port":0}]},{"x":1300,"y":40,"wires":[{"id":"3740c0e.02273c","port":0}]},{"x":600,"y":200,"wires":[{"id":"57f96543.f90014","port":0}]},{"x":850,"y":460,"wires":[{"id":"57f96543.f90014","port":0}]}],"env":[{"name":"SETPOINT","type":"num","value":"20"},{"name":"P_SET","type":"num","value":"1.4"},{"name":"I_SET","type":"num","value":"86400"},{"name":"D_SET","type":"num","value":"0"},{"name":"I_INIT","type":"num","value":"0.5"},{"name":"MAX_SAMP_INT","type":"num","value":"1200"},{"name":"D_SMOOTH","type":"num","value":"0"},{"name":"ENABLE","type":"bool","value":"false"},{"name":"OUT_POW_WHEN_DIS","type":"num","value":"0"}],"meta":{"module":"PID PWM","version":"1.0.0","desc":"PID with PWM developed for boiler heating"},"color":"#E9967A","inputLabels":["input"],"outputLabels":["switch_on","switch_off","duty_s","duty_%","PID_%","duty_call","PID_output_raw","PID_output"],"status":{"x":660,"y":520,"wires":[{"id":"b68243a88e7c3da2","port":0}]}},{"id":"f1a5fc43.3c97d","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0.249","maxout":"1","action":"scale","round":false,"property":"payload","name":"Upper 75% prop","x":600,"y":280,"wires":[[]]},{"id":"3740c0e.02273c","type":"timeprop","z":"c5b37bdc.62ddc","name":"PWM","cycleTime":"300","deadTime":"30","triggerPeriod":"10","invert":false,"x":970,"y":140,"wires":[["ced7cf25.1a82c"]]},{"id":"ced7cf25.1a82c","type":"switch","z":"c5b37bdc.62ddc","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1150,"y":140,"wires":[[],[]]},{"id":"f2327bd2.e4f88","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0","maxout":"300","action":"scale","round":true,"property":"payload","name":"Duty (s)","x":1100,"y":240,"wires":[[]]},{"id":"60e50ce7.969a94","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0","maxout":"100","action":"scale","round":true,"property":"payload","name":"Duty (%)","x":1100,"y":300,"wires":[[]]},{"id":"57f96543.f90014","type":"PID","z":"c5b37bdc.62ddc","name":"PID","setpoint":"${SETPOINT}","pb":"${P_SET}","ti":"${I_SET}","td":"${D_SET}","integral_default":"${I_INIT}","smooth_factor":"${D_SMOOTH}","max_interval":"${MAX_SAMP_INT}","enable":"${ENABLE}","disabled_op":"${OUT_POW_WHEN_DIS}","x":350,"y":260,"wires":[["2c949416e55c666c","6bd50dcf.510a2c"]]},{"id":"6bd50dcf.510a2c","type":"function","z":"c5b37bdc.62ddc","name":"under 10% cutoff","func":"var payload = msg.payload\nif(payload < 0.10)\n    {\n        payload = 0\n    }\nmsg.payload = payload \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":260,"wires":[["60e50ce7.969a94","f2327bd2.e4f88","3740c0e.02273c"]]},{"id":"2c949416e55c666c","type":"range","z":"c5b37bdc.62ddc","minin":"0","maxin":"1","minout":"0","maxout":"100","action":"scale","round":false,"property":"payload","name":"PID Duty (%)","x":590,"y":380,"wires":[["184f4b15e7537d74"]]},{"id":"b68243a88e7c3da2","type":"status","z":"c5b37bdc.62ddc","name":"","scope":null,"x":500,"y":520,"wires":[[]]},{"id":"184f4b15e7537d74","type":"change","z":"c5b37bdc.62ddc","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"op","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":380,"wires":[[]]},{"id":"0d9b4bdf5390b3fa","type":"function","z":"c5b37bdc.62ddc","name":"on/off mode","func":"if (msg.payload < 20.0) { msg.payload = true; } else { msg.payload = false;}\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":60,"wires":[[]]},{"id":"4b0b7924.e0ce38","type":"subflow:c5b37bdc.62ddc","z":"b664267a.c56958","name":"Cons PID","env":[{"name":"P_SET","value":"1.5","type":"num"},{"name":"I_SET","value":"1800","type":"num"},{"name":"D_SMOOTH","value":"5","type":"num"},{"name":"P","value":"8","type":"num"},{"name":"I","value":"30","type":"num"},{"name":"D","value":"15","type":"num"}],"x":720,"y":200,"wires":[["126d6d6f.f2c4e3"],["e61977f.737b708"],["79704fa6.8f0b1","7ed9f2146c9c1de5"],["c2c1e628.907dd","56e8b2f92d264137"],["769cf9e8.a45b78"],["83372335.f9dbb8"],["4b06d485d777a72d","22a17f22.b05088","44fb632f.5b46e4","fd4c1831.46b6b","87cb4190056bc6a8"],["abfd24b4d6bd83bb"]]}]
colinl commented 6 months ago

Sadly I can't make that fail. Was it actually showing NaN when you exported it?