If and else if range gap

Hi all

I am trying to tweak my code a little bit to prevent my relays tripping on the border of a value…

Eg. My thermal sensor trips the relay at 5500ohms, 2nd relay at 4500ohms and 3rd relay at 3600ohms…

I currently have my code like this

if (min < 3600){
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, HIGH);}

else if (min < 4500){
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, LOW);}

else if (min < 5500){
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, LOW);
digitalWrite(RELAY3, LOW);}

I was hoping I could make it so the else if statements would work like this

else if (min > 3700 < 4500){

else if (min > 4600 < 5500){
Leaving a 100 ohm gap in between…

Can anyone advise me the correct way to accomplish this as the above failed…

The error came up with wanting me to put them in brackets but that wouldn’t work either!

Eg
else if (min > 4600); (min < 5500){

I’m really sorry for all the confusion… I’m lost and suck at coding…

else if (min > 3700 && min < 4500)  //greater than 3700 and less than 4500

You might want to add some hysteresis.

Thank you master helibob..

Would this count as hysteresis?

toxsickcity:
Would this count as hysteresis?

No. Hysteresis would involve turning on a relay at a particular value and off at a slightly different value to avoid the system hunting between the on and off states. It ensures that the relay stays in one state or another for at least a short period of time.

if(someVal < limit - 50)
{
  // relay on or off
  ...
  ...
}

if(someVal > limit + 50)
{
  // relay off or on
  ...
  ...
}

Adjust to needs :wink:

So I am assuming that I’d use that example code like this?

if (min < 3600 - 50){
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, HIGH);}
if (min < 3600 + 50){
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, LOW);}

else if (min < 4500 - 50){
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, LOW);}
if (min < 4500 + 50){
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, LOW);
digitalWrite(RELAY3, LOW);}

Can anyone verify this?
As I’m confused thinking that 4500- 50 is just 4450…
And 4500+50 is just 4550 so won’t the relay trip the same way when it hangs around that value?

It is. But imagine that you set the limit using e.g. a keypad or serial input.

Further hard coded numbers are not advisable (I was guilty of that with the value 50). If you use e.g a limit of 4500 and use that limit in different places in your code, you’ll have to replace it everywhere. And if that number is also used for e.g. a delay, you run the risk that you accidentally also change the delay.

The 50 was just an example, by the way; you need to fine tune to your needs.

Lastly be aware that the below has the side effect that if the value is below 3650, it will also be below 4550.

if(value<3650)
{
  ...
  ...
}

if(value<4550)
{
  ...
  ...
}

So with much attempts the solution I tried with the && as helibob helped with was infact not hysteresis

:frowning: :frowning: :frowning: damn it, thought I had a solution that was well… simple…

I was hopeful someone can help to create a way as helibob has mentioned
“Hysteresis would involve turning on a relay at a particular value and off at a slightly different value to avoid the system hunting between the on and off states. It ensures that the relay stays in one state or another for at least a short period of time”

currently with setting ranges of resistances…
min > 3700 && min < 4500
and
min > 4600 && min < 5500

the range works fine but sadly with areas such as the 100 ohms between 4500-4600
all relays stay off!! until the temp hunts below or over the 4500 / 4600!!

I was hoping to somehow use millis to create the hysteresis.
I am already using millis to add 30 seconds of delay for each update of all relays., my millis is before all the relays code to act as the total delay for the entire relays code., Maybe I can manipulate the delay by using the if and else if statements to change the delay.

I would really like to have it so that if the resistance lowers that it will reset the millis.

for example,
if the sensor hits 5000 resistance it would add a millis delay to ensure the relays stay on for 5 minutes instead of 30seconds.

but if the resistance were to hit 4000 I would like the code to end the millis, or change it to 1 second and start over allowing trigger of 2nd relay immediately but forcing the relays on by using millis again for 5 minutes…

I would only want the interruption of millis only when resistance is lowering… NOT Raising.

if the resistance value goes high then the millis value will stay as is, forcing the relays on for the 5 minutes! also turning off each relay as it progresses

I have posted my relays code below to see fully how I have it set

//USED FOR MILLIS DELAY!
 // signed comparison for proper handling of timer rollover
 if((long)(millis() - rolltimera) >= 0) {


//RELAY SECTION FOR CPU OVERHEAT EMERGENCY SHUTDOWN
if (average2 < 2250){ //CPU sensor AC Relay with capacitor to enable relay activation for 5 seconds
  digitalWrite(RELAY5, HIGH); }
  else if (average2 > 4501){
  digitalWrite(RELAY5, LOW);}

  
//RELAY SECTION FOR AUTOMATIC NIGHTTIME LIGHTING
if (average7b < 700){//LDR Sensor
  digitalWrite(RELAY6, HIGH); }
  else if (average7b > 1001){
  digitalWrite(RELAY6, LOW);}

  
//SECTION CONTROL RELAY SWITCH
/*
2480 60c | 2985 55c | 3601 50c | 4541 45c
5324 40c | 6530 35c | 8056 30c | 10000 25c
12500 20c | 15700 15c | 19900 10c 

// also in resistance! Enter Temp in resistance... table above for help.
*/
//RELAY Settings for MINIMUM resistance for all sensors as used in array above
if (min > 0 && min < 4500){ //Enter Sensor Resistance Temp for 5th Fan Speed (FULL)
  digitalWrite(RELAY1,HIGH);
  digitalWrite(RELAY2,HIGH);
  digitalWrite(RELAY3,HIGH);
  digitalWrite(RELAY4,HIGH);}
else if (min > 4600 && min < 5000){ //Enter Sensor Resistance Temp for 4th Fan Speed
  digitalWrite(RELAY1, LOW);
  digitalWrite(RELAY2, HIGH);
  digitalWrite(RELAY3, HIGH);
  digitalWrite(RELAY4, HIGH);}
else if (min > 5100 && min < 5500){ //Enter Sensor Resistance Temp for 3rd Fan Speed
  digitalWrite(RELAY1,LOW);
  digitalWrite(RELAY2,LOW);
  digitalWrite(RELAY3,HIGH);
  digitalWrite(RELAY4,HIGH);}
else if (min > 5600 && min < 6200){  //Enter Sensor Resistance Temp for 2nd Fan Speed
  digitalWrite(RELAY1,LOW);
  digitalWrite(RELAY2,LOW);
  digitalWrite(RELAY3,LOW);
  digitalWrite(RELAY4,HIGH);}
else if (min < 6300){ //Enter Sensor Resistance Temp for 1st Fan Speed (Lowest)
  digitalWrite(RELAY1,LOW);
  digitalWrite(RELAY2,LOW);
  digitalWrite(RELAY3,LOW);
  digitalWrite(RELAY4,LOW);}
  
rolltimera += TimerRelayActivation;} //Delay for FAN SPEED RELAYS (Prevents Relay Hammer)
// delay(50); //Not using delay.. REPLACED WITH MILLIS...

Ty

I was hoping to somehow use millis to create the hysteresis.

Hysteresis is not usually a matter of timing, rather the difference between when something changes state, say from off to on and when it changes state the other way. It is used to prevent the system hunting quickly between on and off.

If you want to ensure that a relay stays on (or off) for a fixed period then you should use the BWOD principle. Save the millis() value when the state change happens. Keep going round loop() with no blocking code until the required period passes then change the state to the opposite.

If you want to measure say temperature and abort the BWOD waiting period early if the temperature limit is reached then introduce a boolean variable to flag that timing is taking place and set it to true when timing is happening and to false either at the end of the timing period or when the temperature exceeds your limit. Make other code execution dependent on the value of the boolean variable.

Hi Ukhelibob

Thanks for your reply… I had a look into bwod and think that timing might not be a good way to.

I think I’d get better results with making as you said on at xx and off at xx

Would it be possible to make the relay trigger in the ranges I specified… but having the co-responding if statements range.

Can you see what I was hoping for… I was wanting the relays to ignore being changed state in those 100ohm ranges between the if statements.

else if (min > 4600 && min < 5000){ //Enter Sensor Resistance Temp for 4th Fan Speed
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, HIGH);
digitalWrite(RELAY3, HIGH);
digitalWrite(RELAY4, HIGH);}
else if (min > 5100 && min < 5500){ //Enter Sensor Resistance Temp for 3rd Fan Speed
digitalWrite(RELAY1,LOW);
digitalWrite(RELAY2,LOW);
digitalWrite(RELAY3,HIGH);
digitalWrite(RELAY4,HIGH);}

Can you tell me what’s required to work that way?
So in this, I would like the relay2 turn on at 5000 and turn off at 5100 not 5001
This would provide the hysteresis
Relay3 turns on at 5500 but turns off at 5600 not 5501

Thanks mate

OP, it’s not clear to me that you’ve yet totally grasped the concept of hysteresis. It’s a non-linear input / output relationship with memory that intentionally creates a dead zone. While the independent variable (input) is within the dead zone range, the dependent variable (output) doesn’t change. Rather, it remains at the value it had before the dead zone was entered.

Since you seem to be working on a cooling application, consider how the thermostat in your home air conditioner works. If it cycled on and off every couple of seconds around the set point, the AC unit would soon burn out. Rather, the thermostat creates a dead zone around the set point and operates as shown in this diagram.

So, if the temperature starts low and rises, the AC unit doesn’t turn on until the room reaches set point + delta. However, once the AC unit is on, it doesn’t turn off until the room temperature falls below set point - delta.

So, why not assign each of your fans an individual set point and delta? Actually, you could probably use the same delta value for all of them -- make it the delta Resistance equivalent of a few degrees. That way, as the temperature rises, successive fans come on as their set point + delta value is exceeded. As the temperature falls, successive fans shut off once the temperature is below their individual set point - delta value.

This technique doesn’t require any messy timing and the fans won’t cycle rapidly due to the hysteresis.

Hi, I understand what it is… I’m having trouble understanding how to implement the stupid H word into my code.

By Delta were you referring to the -50? +50 as someone posted?
Eg

Else if (min < 5000 - 50)

As I see this as simply 4950.
I believe the relay will switch at that 4950 instead of 5000
I don’t see that is giving the code the deadzone.

It’s what I want… 100ohms of deadzone

It's what I want.. 100ohms of deadzone

What range of input values does a range of 100 ohms produce ?

It might be easier (for comprehension at least) to control each fan separately.

if(min>2000)
  {
  turn fan2 on
  }
if (min < 1000)
  {
  turn fan2 off
  }

Replicate that for each fan.

Then you could refactor it with a function ControlFan that takes the relay pin number and the upper and lower limits that apply to it.

First thing I’d do is change the name of your ‘min’ variable. I assume that’s it’s the current temperature reading (in resistance units) since you’re trying to control the fans with it. So, it makes no sense to call it ‘min’ as most people would think that stands for ‘minimum’. Also, since you haven’t yet posted your complete code, I have no idea how you’re actually reading the temperature. So, I’m gonna guess.

Here’s an ugly, bute force outline of a way to do it. There are many optimization possible to make it less ugly and more elegant. But, baby steps ….

const unsigned int fan4SetPoint = 5900;
const unsigned int fan3SetPoint = 5300;
const unsigned int fan2SetPoint = 4800;
const unsigned int fan1SetPoint = 4500;

const unsigned int detlaT = 50;

void setup() {
// Setup Code Goes Here
}

void loop() {
  unsigned int currentTemp;

  currentTemp = GET_NEW_TEMPERATURE_READING();   // You never showed how you do this
  
  if (currentTemp < fan1SetPoint-deltaT) {
    Turn On Fan1;
  }
  if (currentTemp < fan2SetPoint-deltaT) {
    Turn On Fan2;
  }
  if (currentTemp < fan3SetPoint-deltaT) {
    Turn On Fan3;
  }
  if (currentTemp < fan4SetPoint-deltaT) {
    Turn On Fan4;
  }

  if (currentTemp > fan1SetPoint+deltaT) {
    Turn Off Fan1;
  }
  if (currentTemp > fan2SetPoint+deltaT) {
    Turn Off Fan2;
  }
  if (currentTemp > fan3SetPoint+deltaT) {
    Turn Off Fan3;
  }
  if (currentTemp > fan4SetPoint+deltaT) {
    Turn Off Fan4;
  }
}

SECTION CONTROL RELAY SWITCH
/*
2480 60c | 2985 55c | 3601 50c | 4541 45c
5324 40c | 6530 35c | 8056 30c | 10000 25c
12500 20c | 15700 15c | 19900 10c

So we’re basically talking 500ohms for 5 degree C
So 100ohm would be maybe 1 degree but it’s enough.
Plus once I understand how to create this so called deadzone. I can change this to better suit… should I need 2 or 3 degrees of deadzone (200-300ohms)

I am using ohms as I didn’t like it when degree C was being calculated. I still calculate it for serial print so I can refer to it for diagnosis etc… resistance seems to have alot more integers than degrees C… 1 degree or 1.0degree vs 100ohms…

. It’s not linear as you can see 5degrees can be 2000ohms difference… I don’t care as I can make my dead zones as large as I want… as it’s all just numbers in the end.

Let's try this in English rather than in C

Suppose that you want to keep the temperature at about 35 degrees

If you did,
when the temperature is above 35 turn off the heater and when the temperature is below 35 turn on the heater then there could come a point when the heater is being turned on and off in quite rapid succession which will probably be quite bad for the relay and the heater and could be annoying.

However, if you did,
when the temperature is above 38 turn off the heater and when the temperature is below 33 turn on the heater then the relay and heater would turn on and off less frequently and there would be less wear and tear on the system. You would have introduced 5 degrees of hysteresis.

Of course, you don't have to use the actual temperature you can use any values that represent the temperature such as the output from a sensor.

So ‘min’ does stand for minimum… it’s the reading taken from 6 sensors in an array. I found a code to extract Max and min and I use min as the minimum of 6 sensors…
So the hottest component.

I will work that code as a replacement to how I have it setup and will trial it tomorrow… it’s 2.30am in Australia and I’m buggered…

Can I ask this tho…

if (currentTemp < fan2SetPoint-deltaT) {
Turn On Fan2;
}

At 4802ohm and 4798 sorry… I forgot Delta…

4749 and 4751 ohms…
Would this make the relay turn on and off? If sensor fluctuate between the two values?

As I don’t think the code cares that we are using -50? I could be wrong but 4800-50 is 4750… unless -50 works differently than simple maths which is take 50 from my set point…

The code I currently use sort of works this way…
If I had set < 4750 it will hammer at 4751 and 4749. I added a delay for 30sec to stop this but don’t like millis for this as a solution…

I don’t see how this is different to saying the code like this

If (min < 4750){
Turn fan on}

My code was set as above and when sensor fluctuate between + or - few ohms from 4750 the relay is on off on off

I am only asking because my current code which is posted above about 9 to 10 posts back for my relays…
It shows the relays code I use… with some explainations

Note: posted code has a range of resistance… not a set single resistance…
It was single resistance… eg… if (min < 5000) but thought min < 5000 && > 6000) would work for me…

Good

There is no difference between using delta and calculating the raw numbers beforehand. Using delta helps you to add hysteresis using this pattern:

if (currentTemp < fan2SetPoint-deltaT) 
{
   Turn On Fan2;
 }
if (currentTemp > fan2SetPoint+deltaT) {
   Turn Off Fan2;
 }

It’s just a convenience, you can do the calc yourself and put the literals in place instead if desired.