How to create a slow PWM that's less than 1Hz - in another thread?

I am creating a PID AC heater control and plan on using Zero Cross SSRs. I have 4 heating elements and will use 4 SSRs. From my research, seems like 2 second period would be ok for the SSRs and heating elements. I haven’t done any multi-threading, but this may seem like a good time to try…or not. I’m generally looking for some feedback on this. I need to set a target temperature and a heating rate.

I haven’t fully worked through the prototype code, but looking for some feedback on the best way to approach this.

I think I’d like to break up the heating cycling into a seperate method like so:

double heater1On  = PIDHeater(...,...,..)
double heater2On = PIDHeater(......,...)
HeatingCycle(heater1On, heater2On);
TargetNotMet = CheckTargetTemperate();

public void HeatingCycle(double heater1OnPercent , double heater2OnPercent...)
     datetime now = System.DateTime.Now();
     datetime start = now;
     double loopSeconds  =2;
     While(start <= start.AddSeconds(loopSeconds))
          now = System.DateTime.Now();
          heater1.Write( (now.AddSeconds(heater1OnPercent*loopSeconds) <= now ? true : false);
          heater2.Write( (now.AddSeconds(heater2OnPercent*loopSeconds) <= now ? true : false);
          ///...other heaters


(I supposed I could use milliseconds/AddMilliSeconds() for a little more precision)

Do you think this is ok from both a hardware and software perspective?

My first impression is that the control seems rather messy.

double heater1On  = PIDHeater(...,...,..)
double heater2On = PIDHeater(......,...)
HeatingCycle(heater1On, heater2On);
TargetNotMet = CheckTargetTemperate();

You seem to be referring to PID control but then intervening rather than relying on your PID control to NOT call for heating if it’s not required. Your timing requirements can be derived from your PID terms - very slow control terms.

For periods where no heating is required at all you could put your PID into ‘Manual’ and switch the outputs off.

If you have not already seen it I would recommend taking a look at @ Duke Nukem’s excellent PID tutorial in Codeshare

Your control terms will be an order of magnitude slower than those used to control a motor.

@ Sprigo - thanks for the PWM code link. I’ll delve into that. I’m more looking for feedback on the slow PWM part after I get my “on time” from the PID.

It strikes me that this is what’s called for - in an abstract sense:

Have StartHeater and StopHeater - methods.

StartHeader will: a) switch on the heater; b) start a timer to call StopHeater in X seconds.
StopHeater will: a) switch off the heater; b) start a timer to call StartHeater in Y seconds.

There are no sleeps, explicit threads or wasted CPU here, everything that should happen will happen when it should.

If your problem isn’t solved using the above approach, then please explain why so we can understand better what your striving for.


Why bother with PWM? Just use GPIO and set the pins high/low when your PID dictates.

Depending on what you want to accomplish and what constraints you have you might get fine results with a bang bang controller.

Years ago when I wanted to create a freeze protection system, I thought I was going to need a PID controller. Since it was much easier to implement on/off, I started there. I hooked up the system to the internet and watched the results. Since I wanted to make sure things didn’t freeze, I wasn’t too concerned about overshoot. The results on a couple of different systems looked good enough. The temperature did overshoot, but for a freeze protection system I thought that was probably a good thing.

If you want to hold a set point and especially if you want to have fast step response and low/no overshoot, you will need to use a more sophisticated controller and you will need to tune it to the dynamics of the system.

On my systems I have a 30s loop. It reads the temp from one or more sensors. The controller then decides to turn the heater on or off. I use Dallas (now Maxim) OneWire sensors. Beware that they can return the wrong answer when they fail or are not powered correctly. The controller makes a decision to turn on the heat if any sensor is too cold and none are too hot, otherwise it will turn off the heat.

The controller takes an IRelay interface (which allows me to use the same code on systems that use GPIO to a relay or 315MHz transmitter to an RF switch). I did add the ability to have the IRelay turn itself off after a certain number of milliseconds, but don’t use that feature with bang-bang.

Later, I added the ability to vent and cool, which I use for my (aerated static) compost pile.

@ Frogmore - If a fault should ocour and the heater stays on indefinitely, how long until it catches fire?

Good question. System #1 is an outdoor water hydrant/faucet. It was designed to stay on always. Since I added insulation to it, it does get to 150 deg F, but is unlikely to catch fire. System #2 uses a pump to move hot water to the cold water line. No fire hazard there, just wasted energy. System #4 uses a combination of incandescent lights (25W total), 80W low temp floor/foot heater and 200W small fan forced ceramic heater. It used to only use the small incandescent lights, but that was not enough total heat for the area when it got below 25F (which it had not done until recently). The exit temperature of the 200W heater is not very high, so the risk is reasonably low. I probably should put in a secondary cutoff. But, since I started validating the input from the sensors, I have not had the system put the heat on when it was not needed.

System #5 uses motorcycle grip heaters and a 25W silicone encased heater to keep a water meter from freezing. It has some insulation around it that is probably flammable, but it is also controlled by a GPIO driven relay. If the heaters came on on a really hot day, there might be an issue. But, it would have limited impact, since it is away from anything else.

The last system is the compost pile and I turns on a blower. If the blower stays on too Lon the compost gets too cold. If it doesn’t turn on, it becomes a non-aerated pile. So no issue there.

Of course, remember that I am a trained professional, don’t try this at home :wink:


@ KorporalKernel - I was just thinking out loud, and trying to emulate a smooth/controlled heating profile… think [em]reflow oven[/em] 8)

@ ianlee74 @ Frogmore - I will probably end up implementing a solution like that at .5 to 2Hz. From what I understand of Zero Cross SSRs and resistive heating elements with “high” speed PWM isn’t the best solution. Basically GPIO/bit bang a really slow PWM.

It seems like the PID code example posted above would work for me. I could complicate it by making a multi-variable control(heating rate/ and target heat), but I could poll the set temperature and then use the control to increase the temperature at the set rate and then stop and change the PID control to maintain the temperature and so on…I’ve got a few SSRs and some Thermocouples on the way so I’ll keep this updated

PWM in general with any form of switching is not a good idea. Also remember that the thermal profile of the device you’re talking about is typically going to be seconds before any change in temperature is likely - so you’re best off just doing simple bit-bang on/off control of the SSR. In fact, check out the Sous Vide example by @ Duke Nukem for inspiration

I got it it working with the PID control. I did some tuning, but it still needs some work. There’s some overshoot. Also, I’m working on some type of feed-forward control to control the heating rate along with setpoint, but it might not be necessary. That said, naturally, the top heater heats up faster than the bottom. I’m going to add more insulation and re-tune the system.

Here’s a graph of the first run: