Heating element control PWM Yes or NO

Hello all, its been a few since i have been on. I have been cleaning up some of my dashboard and planning next stage.
I hope I really dont sound ignorant here. but I have already been doing some searches and i have a few questions about PWM and heating elements.

  1. from what i have read I can not use PWM with a Solid State Relay,
  2. can i use it with a coil relay. if so will the constant turning off and on cause the coil relay to wear out sooner?
    I had to add this,
    I'm using 3phase heating elements. where I already use a contactor to control the actual power going to element.
    I have to use low voltage (dc) first because i use a float switch to dissable the power if the level is to low.
    so in reallity, I use low voltage to control either a solid state relay or a coil relay, which in turns provides 110v to contactor , to close the circuit there.

right now i have heater set up like i have my fermenters, however its reversed logic (above or equal to target is off now )

[{"id":"157e819a9be636f0","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"0cae5ff764274307","type":"change","z":"157e819a9be636f0","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"HLTtarget","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":352.0071105957031,"y":254.00568581237792,"wires":[["de64d6f0d6b0e7e3","886783c9f1ec8119"]]},{"id":"de64d6f0d6b0e7e3","type":"debug","z":"157e819a9be636f0","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":518.3936347961426,"y":264.64960766448974,"wires":[]},{"id":"886783c9f1ec8119","type":"change","z":"157e819a9be636f0","name":"","rules":[{"t":"set","p":"HLTtarget","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":547.0229721069336,"y":224.1783437789917,"wires":[[]]},{"id":"1f6d65caaec98c3b","type":"ui_dropdown","z":"157e819a9be636f0","name":"","label":"","tooltip":"","place":"Select option","group":"34c8e5f1.3881fa","order":5,"width":4,"height":1,"passthru":true,"multiple":false,"options":[{"label":"Mash Temp","value":"170","type":"str"},{"label":"Sanitize Temp","value":"185","type":"str"},{"label":"Boiling Temp","value":"205","type":"str"},{"label":"Off","value":"0","type":"str"}],"payload":"","topic":"target_temperature","x":191.09669494628906,"y":252.55601025238036,"wires":[["0cae5ff764274307"]]},{"id":"340f56965055b6e7","type":"change","z":"157e819a9be636f0","name":"","rules":[{"t":"set","p":"HLTambient","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":544.0070114135742,"y":448.00571632385254,"wires":[["65a17d815f706559","9b2d73d1790b48ea"]]},{"id":"65a17d815f706559","type":"switch","z":"157e819a9be636f0","name":"","property":"HLTtarget","propertyType":"global","rules":[{"t":"lte","v":"HLTambient","vt":"global"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":722.201171875,"y":407.6003074645996,"wires":[["185055d6bd6c8371"],["c9be54bb9bfd0344"]]},{"id":"185055d6bd6c8371","type":"change","z":"157e819a9be636f0","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"off","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":862.6496658325195,"y":380.6718330383301,"wires":[["1f65dd92be3df989","1a2b0dd1caf61b8f"]]},{"id":"c9be54bb9bfd0344","type":"change","z":"157e819a9be636f0","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":865.8202972412109,"y":426.50273990631104,"wires":[["f9a5d794d1fca570","1a2b0dd1caf61b8f"]]},{"id":"1f65dd92be3df989","type":"debug","z":"157e819a9be636f0","name":"off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":949.943187713623,"y":328.0494689941406,"wires":[]},{"id":"1a2b0dd1caf61b8f","type":"change","z":"157e819a9be636f0","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"cmnd//POWER","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1055.018325805664,"y":402.9123659133911,"wires":[["f30f0c2fc09db0f8"]]},{"id":"f9a5d794d1fca570","type":"debug","z":"157e819a9be636f0","name":"on","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":959.968017578125,"y":477.08672618865967,"wires":[]},{"id":"6b467fb802b70a70","type":"change","z":"157e819a9be636f0","name":"set payload to Temperature value","rules":[{"t":"move","p":"payload.Temperature","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":482.0087432861328,"y":306.55677604675293,"wires":[["a013a89a77ebf97a","cb1853bc34ef4f01","340f56965055b6e7"]]},{"id":"a013a89a77ebf97a","type":"ui_template","z":"157e819a9be636f0","group":"34c8e5f1.3881fa","name":"HLT","order":4,"width":6,"height":6,"format":"<div id=\"{{'gauge_'+$id}}\" class=\"g-container\" style=\"--gauge-value:0; --container-size:6; --gn-distance:14; --ga-tick-count:22; --ga-subtick-count:220; --g-unit:''°F'\">\n    <div id=\"bgr\" class=\"g-body\">\n        <div class=\"g-ring\">\n            <div class=\"g-rivets\">\n                <div class=g-rivet></div>\n                <div class=g-rivet></div>\n                <div class=g-rivet></div>\n                <div class=g-rivet></div>\n            </div>\n            <div class=\"g-plate\">\n                <div class=\"g-ticks\">\n                    <div class=\"g-tick\" style=\"--ga-tick:1;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:3;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:5;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:7;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:9;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:11;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:13;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:15;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:17;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:19;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:21;\"></div>\n                    <div class=\"g-tick\" style=\"--ga-tick:23;\"></div>\n                </div>\n                <div class=\"g-ticks\">\n                    <div class=\"g-subtick\" style=\"--ga-tick:11;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:31;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:51;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:71;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:91;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:111;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:131;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:151;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:171;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:191;\"></div>\n                    <div class=\"g-subtick\" style=\"--ga-tick:211;\"></div>\n                    \n                </div>\n               <div class=\"g-nums\">\n                    <div class=\"g-num\" style=\"--ga-tick:1;\" >0</div>\n                    <div class=\"g-num\" style=\"--ga-tick:3;\">20</div>\n                    <div class=\"g-num\" style=\"--ga-tick:5;\">40</div>\n                    <div class=\"g-num\" style=\"--ga-tick:7;\">60</div>\n                    <div class=\"g-num\" style=\"--ga-tick:9;\">80</div>\n                    <div class=\"g-num\" style=\"--ga-tick:11;\">100</div>\n                    <div class=\"g-num\" style=\"--ga-tick:13;\">120</div>\n                    <div class=\"g-num\" style=\"--ga-tick:15;\">140</div>\n                    <div class=\"g-num\" style=\"--ga-tick:17;\">160</div>\n                    <div class=\"g-num\" style=\"--ga-tick:19;\">180</div>\n                    <div class=\"g-num\" style=\"--ga-tick:21;\">200</div>\n                    <div class=\"g-num\" style=\"--ga-tick:23;\">220</div>\n                    \n                </div>\n                <div class=\"g-label\">HLT </div>\n                <div class=\"g-needle\"></div>\n                <div class=\"g-needle-ring\"></div>\n                <div id=\"{{'gauge_val_'+$id}}\" class=\"g-val\"></div>\n            </div>\n        </div>\n    </div>\n</div>\n<script>\n(function(scope) {\n    let min = 0;\n    let max = 100;\n  scope.$watch('msg', function(msg) {\n    if (msg) {\n      // Do something when msg arrives\n        const v = Math.floor(((msg.payload - min) / (max - min)) * (100 * 0.46));\n        const d = Math.floor(((msg.payload - min) / (max - min)) * 100);\n        document.getElementById('gauge_'+scope.$id).style.setProperty('--gauge-value', v);\n        document.getElementById('gauge_val_'+scope.$id).innerText = d;\n    }\n   \n  });\n})(scope);\n</script>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","x":767.8924942016602,"y":345.8119659423828,"wires":[[]]},{"id":"cb1853bc34ef4f01","type":"debug","z":"157e819a9be636f0","name":"boil","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":769.4444961547852,"y":291.1106357574463,"wires":[]},{"id":"f30f0c2fc09db0f8","type":"debug","z":"157e819a9be636f0","name":"msgtopic","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1230.2810897827148,"y":401.9162311553955,"wires":[]},{"id":"7647817384e0b5fa","type":"inject","z":"157e819a9be636f0","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"212","payloadType":"str","x":196.27983283996582,"y":315.93323612213135,"wires":[["340f56965055b6e7","a013a89a77ebf97a"]]},{"id":"ceff910bd609d4eb","type":"inject","z":"157e819a9be636f0","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"95","payloadType":"str","x":194.28125762939453,"y":364.9361071586609,"wires":[["340f56965055b6e7","a013a89a77ebf97a"]]},{"id":"fd12c5689c13e7db","type":"inject","z":"157e819a9be636f0","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"170","payloadType":"str","x":198.28125762939453,"y":410.9361448287964,"wires":[["340f56965055b6e7","a013a89a77ebf97a"]]},{"id":"9b2d73d1790b48ea","type":"debug","z":"157e819a9be636f0","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":574.2840957641602,"y":489.0099849700928,"wires":[]},{"id":"34c8e5f1.3881fa","type":"ui_group","name":"test","tab":"85b0e00f12eded88","order":1,"disp":true,"width":6,"collapse":false},{"id":"85b0e00f12eded88","type":"ui_tab","name":"test 1","icon":"dashboard","disabled":false,"hidden":false}]

For the pwm, have a look at node-red-contrib-timeprop, it is designed for exactly the purpose you describe.
Also, for the closed loop control you could try node-red-contrib-pid.
I am biased in these suggestions as I am the author.

In my experience, all heating controls use PID except in very few, very specialist designs.

PWM tends to create lots of radiated noise and is not needed for the very much finer control it is able to give due to comparative 'sluggishness' of a heater to respond to the input.

For virtually all applications, PID is the go to for this providing excellent control once the PID numbers have been worked out.

I can recommend node-red-contrib-pid from @Colin - it just works, but then you can tweak to your hearts content for the 'perfect' control (no undershoot, no overshoot, perfect critical damping - read the help!)

1 Like

In fact the technique used by node-red-contrib-pid, which is to cycle the power on and off at a rate defined by the user (typically a few minutes) is just slow PWM. The term is generally used to describe much faster switching however.

1 Like

As an FYI...
The 'special' applications for PWM I am used to were for VERY tight temperature control where there was a drastic change in temperature, but the thermal load was very small. i.e. draughts would make a big difference to the temperature of a substrate during a process, or changes of flow in chemicals would cause a rapid change in temperature which would affect the process. There were controls for both heating and cooling to help keep the control as the process itself could induce heat. There could even be heating and cooling ramps involved. PID would work, but it was found PWM was better in these circumstances.

Bigger heaters were used compared to what would normally be required in 'normal' circumstances. The radiated noise was suppressed as far as practical, but not a problem in the industrial environment they were in.

ok so the PID doesnt actually use the PWM , but acts like it.
so here is my main concern with heating elements.
so im using them to boil sugar water (wort/beer)
low wat density heating elements are prefered but are not effecient.
im using a high watt density element wich will burn the sugars.
when im heating the water up its not a big deal. and to be honest when doing 200 or 300 gallons of water a little overshoot will not hurt the process.
i just need to figure out how to keep from burning up the sugars.
ill do a little reading on the PId controller again , its been about a year or longer since i had initially installed it into my pallet from when you @Colin had helped me in the earlier stages of my project.
thanks for the intel gentlemen.

No, the pid node produces a value between 0 and 1 indicating how much power to apply. You can then use the timeprop node to turn that into a time proportioned on/off signal to control your solenoid.

You can limit the amount of power if you want, so if you want to limit it to a max of 50% for example then you can feed the output of the PID through a Range node to scale it down from 0:1 to 0:0.5. Then the timeprop node will never generate more that 50% output.

1 Like

ok so i finally got the 3phase all wired up, the ferrels welded to the tanks.
and 3phase toggle switches to turn off manually (for isolation)
also so i can run 2 elements in one tank or the other, or 1 element in each tank,
i hard wired in ranco temp controllers in. however from the controller to the contactors I added a ssr so it can cut power if the float switch drops, and i can easilly tie in my own temp controls from node red. it will allow me to place a 3 way switch in control panel where i can just have power on and let the ranco temp controller run things, or it has to go through the raspberry pi to control temps.
this way i have a back up if i fry the pi, but also allows me some testing without disabling the whole system.
pictures coming soon.

1 Like

Patently false. I work with several ovens that use PWM through a SSR array on a three phase power source that runs the coils to control temperature. Anyone who says you can't use SSRs for temperature control or that you can't use them for 3ph applications will have to show me why my ovens don't work.

The trick with the PWM is to stretch it out to a useful pulse time. This is anywhere from the frequency of your mains (i.e. 50 or 60Hz or 1/50 to 1/60 of a second) to something like one second. My pulse length is about half a second. Your PWM will turn on the SSRs for that period of time and heat your coils.

And this setup is very precise. I can maintain a temperature in my ovens of .05°C over the course of many days. It all depends on how reactive and precise/accurate your temperature monitoring is. There's absolutely no reason you should expect anything different than being able to maintain less than 1°F or C with a semi-decent PWM setup using SSRs.

And good luck on the project. Sounds awesome!

For now I'm letting ranco controllers monitor temp, in hlt is not critical just had to be close to 170, in boil kettle i need it to boil, the issue is i have high watt density elements, and if i don't control work pwm they will burn the sugars needed for making the beer,

Right. You have to do what you need to and make it work. The point I was trying to make is don't think you're limited in control options because someone said you can't use SSRs in your application. You totally can and if you choose to at some point, more power to you. But do what you have to do right now to control your heat. Options are explored much more easily when you're succeeding.