Multiple sensors - multiple if-else if statements to set state machine

Hello everybody

I have 2 DS18B20 and 1 DHT-22.

I want to read and compare them to set up a state machine. Therefor:

ex:
If (Temp1>Temp2 && Temp3<Temp2){
ABC.state = GO;
} // if

and that state would be use in a switch case statement to set the actors.

Here is the relevant part of the actual code:

if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minDay || grTEMPControl[HOT].value<grTEMPControl[HOT].minDay && grTEMPControl[OUT].value<grTEMPControl[OUT].minDay)
{
// AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP<28)
Serial.println ("TEMPLOWBOTH");
} // if
else if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minDay || grTEMPControl[HOT].value<grTEMPControl[HOT].minDay && grTEMPControl[OUT].value>grTEMPControl[OUT].minDay)
{
// AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP>28)
Serial.println ("TEMPLOWIN");
} // else if
else if (grTEMPControl[AMBIENT].value>grTEMPControl[AMBIENT].maxDay || grTEMPControl[HOT].value>grTEMPControl[HOT].maxDay && grTEMPControl[OUT].value>grTEMPControl[OUT].maxDay)
{
// AMBIENTTEMP>30 || HOTSPOT>40 && OUTTEMP>30)
Serial.println ("TEMPHIGHBOTH");
} // else if
else if (grTEMPControl[AMBIENT].value>grTEMPControl[AMBIENT].maxDay || grTEMPControl[HOT].value>grTEMPControl[HOT].maxDay && grTEMPControl[OUT].value<grTEMPControl[OUT].maxDay)
{
// AMBIENTTEMP>30 || HOTSPOT>40 && OUTTEMP <30)
Serial.println ("TEMPHIGHIN");
} // else if
/*---Night---*/
else if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minNight || grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value<grTEMPControl[OUT].minNight)
{
// AMBIENTTEMP<18 || HOTSPOT<22 && OUTTEMP < 18)
Serial.println ("TEMPNIGHTLOWBOTH");
} // else if
else if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minNight || grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value>grTEMPControl[OUT].maxNight)
{
// AMBIENTTEMP<18 || HOTSPOT<22 && OUTTEMP > 22)
Serial.println ("TEMPNIGHTLOWIN");
} // else if
else if (grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value>grTEMPControl[OUT].maxNight)
{
// HOTSPOT>25 && OUTTEMP > 22)
Serial.println ("TEMPNIGHTHIGHBOTH");
} // else if
else if (grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value<grTEMPControl[OUT].maxNight)
{
// HOTSPOT>25 && OUTTEMP < 22)
Serial.println ("TEMPNIGHTHIGHIN");
} // else if
else{
Serial.print("NORMAL"); // .state = 0
} // else

And here the rest (with some bugs remaining, that I wasnt able to solve yet):

/*---Libraries---*/
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>


/*---Temperature and humidity related variables---*/
#define HOT    0    // DS18B20 HotSpot
#define AMBIENT    1    // DS18B20 Ambient
#define OUT 2    // DHT-22 Outside

#define dhtOut 0
#define dhtHot 1
#define dhtAmbient 2


#define HOTHUM 3
#define AMBIENTHUM 4


/*---Temp States---*/
#define TEMPLOWBOTH       0
#define TEMPLOWIN      1
#define TEMPHIGHIN         2
#define TEMPHIGHBOTH     3
#define TEMPNIGHTLOWBOTH      4
#define TEMPNIGHTLOWIN    5
#define TEMPNIGHTHIGHBOTH    6
#define TEMPNIGHTHIGHIN    7
#define NORMALDAY

/*---Variables---*/
unsigned long timeNow;
unsigned long dhtStab = 0;
int dhtIntervall = 2000;

/*---Temperature and humidity related array indexes for TempHumPin---*/
#define DHT22OUT    0    // DHT 22 room temperature
#define DHT22HOT     1 // humidity HotSpot
#define DHT22AMBIENT    2 // humidity ambient
#define ONE_WIRE_BUS 3    // 2xDS18B20 HotSpot and Ambient

int TempHumPin[4] = {2, 3, 4, 8};


#define FAN XXX        // ventilator, green LED for testing, Pin 13

/*---DS18B20---*/
/* Create OneWire Object and references to Dallas */
OneWire oneWire(TempHumPin[ONE_WIRE_BUS]); // OneWire object
DallasTemperature sensors(&oneWire); // oneWire reference to Dallas Temperatur
/* Addresses for DS18B20 */
DeviceAddress HotAdr = { 0x28, 0x6F, 0xB6, 0xC5, 0x17, 0x13, 0x01, 0x45 }; // Temp 1 (Hotspot)
DeviceAddress AmbientAdr = { 0x28, 0xAA, 0x3A, 0xC6, 0x1D, 0x13, 0x02, 0xDB }; // Temp 2 (Ambient)
/* Set resolution to 10bit (9, 10, 11, 12 possible - lower is faster) */
//sensors.setResolution(HotAdr, 10);
//sensors.setResolution(AmbientAdr, 10);

/*---Define DHT---*/
#define DHTTYPE DHT22 // which DHT sensor is in use?

typedef struct
{
    const byte          pin;
    const int    maxDay;
    const int    minDay;
    const int    maxNight;
    const int    minNight;
    float    value;
    byte    valPWM;        // ???
    byte                state;
}structTEMPControl;

structTEMPControl grTEMPControl[] =
{
    {
    // HotSpot
    .pin = HotAdr,    // addresse DS18B20 Nr 1
    .maxDay = 40,
    .minDay = 30,
    .maxNight = 25,
    .minNight = 22,
    .value = sensors.getTempC(HotAdr),    // mesure temperature DS18B20
    .valPWM = 0,
    .state = 0
    }, // HotSpot
    {
    // Ambient
    .pin = AmbientAdr,    // addresse DS18B20 Nr 2
    .maxDay = 30,
    .minDay = 28,
    .maxNight = 0, // not available
    .minNight = 18,
    .value = sensors.getTempC(AmbientAdr),    // mesure temperature DS18B20
    .valPWM = 0,
    .state = 0
    }, // Ambient
    {
    // Outside
    .pin = TempHumPin[DHT22OUT],
    .maxDay = 30,
    .minDay = 28,
    .maxNight = 22,
    .minNight = 18,
//???How to do?    .value = dhtObjects[dhtOut].readTemperature(),    // mesure temperature DHT-22
    .valPWM = 0,
    .state = 0
    }, // Outside
}; // grTEMPControl


void setup()
{
/*---Declare and start Objects---*/
//POINTER???
// https://forum.arduino.cc/index.php?topic=141908.0
int dhtObjects[3] = {dhtOut, dhtHot, dhtAmbient};
for (int i=0; i<3; i++){
DHT dhtObjects[i] (TempHumPin[i], DHTTYPE);
dhtObjects[i].begin(); // start DHT-22 Objects
} // for

Serial.begin(9600);
sensors.begin(); // start sensors

for (int i=0; i<4; i++){
pinMode(TempHumPin[i], INPUT);
grTEMPControl[i].state = 0;
} // for

} // setup()


void loop(){
timeNow = millis();
/*---Sanity Check---*/
if (isnan(OUT)) {
        Serial.println("Can not read from DHT");
        return;
} // if
else if (HOT == -127.00){
Serial.println("Cannot mesure HotSpot");
return;
} // else if
else if (AMBIENT == -127.00){
Serial.println("Cannot mesure Ambient");
return;
} // else if
else{
if (timeNow - dhtStab > dhtIntervall)
sensors.requestTemperatures(); // read temperatures of all DS18B20
{
/*---Day---*/
if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minDay || grTEMPControl[HOT].value<grTEMPControl[HOT].minDay && grTEMPControl[OUT].value<grTEMPControl[OUT].minDay)
{
// AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP<28)
Serial.println ("TEMPLOWBOTH");
} // if
else if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minDay || grTEMPControl[HOT].value<grTEMPControl[HOT].minDay && grTEMPControl[OUT].value>grTEMPControl[OUT].minDay)
{
// AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP>28)
Serial.println ("TEMPLOWIN");
} // else if
else if (grTEMPControl[AMBIENT].value>grTEMPControl[AMBIENT].maxDay || grTEMPControl[HOT].value>grTEMPControl[HOT].maxDay && grTEMPControl[OUT].value>grTEMPControl[OUT].maxDay)
{
// AMBIENTTEMP>30 || HOTSPOT>40 && OUTTEMP>30)
Serial.println ("TEMPHIGHBOTH");
} // else if
else if (grTEMPControl[AMBIENT].value>grTEMPControl[AMBIENT].maxDay || grTEMPControl[HOT].value>grTEMPControl[HOT].maxDay && grTEMPControl[OUT].value<grTEMPControl[OUT].maxDay)
{
// AMBIENTTEMP>30 || HOTSPOT>40 && OUTTEMP <30)
Serial.println ("TEMPHIGHIN");
} // else if
/*---Night---*/
else if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minNight || grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value<grTEMPControl[OUT].minNight)
{
// AMBIENTTEMP<18 || HOTSPOT<22 && OUTTEMP < 18)
Serial.println ("TEMPNIGHTLOWBOTH");
} // else if
else if (grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minNight || grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value>grTEMPControl[OUT].maxNight)
{
// AMBIENTTEMP<18 || HOTSPOT<22 && OUTTEMP > 22)
Serial.println ("TEMPNIGHTLOWIN");
} // else if
else if (grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value>grTEMPControl[OUT].maxNight)
{
// HOTSPOT>25 && OUTTEMP > 22)
Serial.println ("TEMPNIGHTHIGHBOTH");
} // else if
else if (grTEMPControl[HOT].value<grTEMPControl[HOT].minNight && grTEMPControl[OUT].value<grTEMPControl[OUT].maxNight)
{
// HOTSPOT>25 && OUTTEMP < 22)
Serial.println ("TEMPNIGHTHIGHIN");
} // else if
else{
Serial.print("NORMAL"); // .state = 0
} // else
timeNow = dhtStab;
} // if
} // else
} // loop

This results in many if / else if statements.

Is there another way to do this?

Thank you!

moses

The clearest way to do this is to use the "switch case" statement. See:

https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/

Example:

switch (var) {
  case label1:
    // statements
    break;
  case label2:
    // statements
    break;
  default:
    // statements
    break;
}

This results in many if / else if statements.

So? If the resulting code is easy to read (your's is NOT) and easy to understand, then the number of lines of code is irrelevant.

YourcodeCOULDbeeasytoreadifyoufoundyourspacekeynowandthen.

Nested if statements are easier to understand, and get right and have full coverage, than compound if statements.

Hello

Thank you all for the replies.

@terryking228 I was also thinking about switch case. But in this case I would only have one variable to test for and I would need discrete cases? I wouldn't know how to reach either one.

@PaulS Yes, true. Spaces would be good for readability... The "if" or "else if" statements all need to be at the same level. I therefore couldn't work with nested if statements, could i?

Thank you,

moses

grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minDay

One thing that you can do to reduce repetitive clutter like this is to put this code into a function that has a useful name. Then you can replace it with something like belowDayMin(grTEMPControl[AMBIENT]) and it’s easier on the eyes to read.

It also has the advantage that if you ever want to change how those conditions work, you only need to change it in the functions rather than track down every instance of where you’re using that condition.

I think this is what Paul was suggesting…

If (Temp1>Temp2 && Temp3<Temp2){
ABC.state = GO;
} // if
if (Temp1>Temp2) {
  if(Temp3<Temp2){
    ABC.state = GO;
  }
}

Also remember you can split long statements onto many lines. I often write this…

if (Temp1>Temp2 
      && Temp3<Temp2){
  ABC.state = GO;
}

Thank you MorganS and Jiggy-Ninja

@MorganS
Splitting lines is a good idea. Thanks.

@Jiggy-Ninja
I am sorry. I am too unexperienced to fully understand.

Does your suggestions mean that the code you put would be in a function?
Would I therefore create functions for any possible event?
How to correctely write the function to pass values to and from the function? As I understand “belowDayMin” would be the function?

belowDayMin(grTEMPControl[AMBIENT])

Would I therefore write for the function:

float belowDayMin(grTEMPControl[AMBIENT])
{
grTEMPControl[AMBIENT] = grTEMPControl[AMBIENT].value<grTEMPControl[AMBIENT].minDay

Return (grTEMPControl[AMBIENT])
}

Or is “grTEMPControl[AMBIENT]” something you would call from the struct?

Thank you all!

moses

Describe in high level what you are trying to accomplish with your temperature if-conditions. It's difficult to decipher from tangled buggy mess what the intentions are and propose better alternatives.

bool belowDayMin(structTEMPControl control)
{
  return control.value < control.minDay;
}

Personally, I find it easier to read if you put the if statement on multiple lines, the single long line is cumbersome unless you have a very wide monitor with small text.

/*---Day---*/
      if (grTEMPControl[AMBIENT].value < grTEMPControl[AMBIENT].minDay
          || grTEMPControl[HOT].value < grTEMPControl[HOT].minDay
          && grTEMPControl[OUT].value < grTEMPControl[OUT].minDay)
      {
        // AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP<28)
        Serial.println ("TEMPLOWBOTH");
      } // if
      else if (grTEMPControl[AMBIENT].value < grTEMPControl[AMBIENT].minDay
               || grTEMPControl[HOT].value < grTEMPControl[HOT].minDay
               && grTEMPControl[OUT].value > grTEMPControl[OUT].minDay)
      {
        // AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP>28)
        Serial.println ("TEMPLOWIN");
      } // else if
      else if (grTEMPControl[AMBIENT].value > grTEMPControl[AMBIENT].maxDay
               || grTEMPControl[HOT].value > grTEMPControl[HOT].maxDay
               && grTEMPControl[OUT].value > grTEMPControl[OUT].maxDay)
      {
        // AMBIENTTEMP>30 || HOTSPOT>40 && OUTTEMP>30)
        Serial.println ("TEMPHIGHBOTH");
      } // else if
      else if (grTEMPControl[AMBIENT].value > grTEMPControl[AMBIENT].maxDay
               || grTEMPControl[HOT].value > grTEMPControl[HOT].maxDay
               && grTEMPControl[OUT].value < grTEMPControl[OUT].maxDay)
      {
        // AMBIENTTEMP>30 || HOTSPOT>40 && OUTTEMP <30)
        Serial.println ("TEMPHIGHIN");
      } // else if
      /*---Night---*/
      else if (grTEMPControl[AMBIENT].value < grTEMPControl[AMBIENT].minNight
               || grTEMPControl[HOT].value < grTEMPControl[HOT].minNight
               && grTEMPControl[OUT].value < grTEMPControl[OUT].minNight)
      {
        // AMBIENTTEMP<18 || HOTSPOT<22 && OUTTEMP < 18)
        Serial.println ("TEMPNIGHTLOWBOTH");
      } // else if
      else if (grTEMPControl[AMBIENT].value < grTEMPControl[AMBIENT].minNight
               || grTEMPControl[HOT].value < grTEMPControl[HOT].minNight
               && grTEMPControl[OUT].value > grTEMPControl[OUT].maxNight)
      {
        // AMBIENTTEMP<18 || HOTSPOT<22 && OUTTEMP > 22)
        Serial.println ("TEMPNIGHTLOWIN");
      } // else if
      else if (grTEMPControl[HOT].value < grTEMPControl[HOT].minNight
               && grTEMPControl[OUT].value > grTEMPControl[OUT].maxNight)
      {
        // HOTSPOT>25 && OUTTEMP > 22)
        Serial.println ("TEMPNIGHTHIGHBOTH");
      } // else if
      else if (grTEMPControl[HOT].value < grTEMPControl[HOT].minNight
               && grTEMPControl[OUT].value < grTEMPControl[OUT].maxNight)
      {
        // HOTSPOT>25 && OUTTEMP < 22)
        Serial.println ("TEMPNIGHTHIGHIN");
      } // else if
      else {
        Serial.print("NORMAL"); // .state = 0
      } // else

It would also help if you put parenthesis around part of the condition statement, its unclear whether your statement

condition1 || condition2 && condition3

should be read as

(condition1 || condition2) && condition3

or

condition1 || (condition2 && condition3)

The compiler will have an order of precedence for logical operations, but easier to read if you make it explicit exactly what you want, and avoids problems where your interpretation of the statement doesn’t match the compilers.

As far as creating functions for the conditional statements, you could do something like this:

boolean TempLowBoth() {
  return ((grTEMPControl[AMBIENT].value < grTEMPControl[AMBIENT].minDay
       || grTEMPControl[HOT].value < grTEMPControl[HOT].minDay)
      && grTEMPControl[OUT].value < grTEMPControl[OUT].minDay);
}

boolean TempLowIn() {
  return (grTEMPControl[AMBIENT].value < grTEMPControl[AMBIENT].minDay
      || grTEMPControl[HOT].value < grTEMPControl[HOT].minDay
      && grTEMPControl[OUT].value > grTEMPControl[OUT].minDay);
}

boolean TempHighBoth() {
  return (grTEMPControl[AMBIENT].value > grTEMPControl[AMBIENT].maxDay
     || grTEMPControl[HOT].value > grTEMPControl[HOT].maxDay
     && grTEMPControl[OUT].value > grTEMPControl[OUT].maxDay);
}

Then your code would look like this:

/*---Day---*/
      if (TempLowBoth())
      {
        // AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP<28)
        Serial.println ("TEMPLOWBOTH");
      } // if
      else if (TempLowIn())
      {
        // AMBIENTTEMP<28 || HOTSPOT<30 && OUTTEMP>28)
        Serial.println ("TEMPLOWIN");
      } // else if
      else if (TempHighBoth())
      ...........

Thank you jiggy-Ninja and david-2018

Ok so the functions would just return 1 or 0 if the conditions are true? And the if statement will only be executed if the return value is 1?

I guess (x || y) && z; would best suite my needs. Because it needs to be the one or the other and the && condition needs to be added afterwards.

What is the relationship of the following compared to the struct?

bool belowDayMin(structTEMPControl control)
{
  return control.value < control.minDay;
}

Does this creat a new variable in the struct called “control” or would I have to define it before in the struct? Or does it actually create a new struct called “control” with its items called “value” and “minDay”. How does it receive the values defined in the struct such as the value for “minDay”?

I am happy that little by little my knowledge of Arduino coding improves even though there is still a long long way to go…

Thank you again!

That copies the entire struct into a local variable called control. After the function returns, that variable “goes out of scope” and cannot be accessed again.

When you call the function again, it does a new copy.

You can also “pass by reference” so there is no copying and changes made to the contents of control will change the original. Look it up in any C reference.

Thank you MorganS

I will read up on “pass by reference”. Is it correct, that the other way which copies the struct is called “pass by value”?

I really like the struct way of dealing with this situation. I realized however that there is one more question concerning this.

bool belowDayMin(structTEMPControl control)
{
  return control.value < control.minDay;
}

As this would copy the whole struct it would also copy the different instances? How do I access them? How would I call the function correctly to access the different sensors?

To call the function?

belowDayMin(control);

Would I add anywhere which of the sensors “HOT”, “AMBIENT”, “OUT” is concerned?

belowDayMin[HOT](control);

or rather:

belowDayMin([HOT].control);

Or which other way would be correct?

Thank you!

Control is what you call the struct when you're using it inside the belowDayMin function. It's a single struct that knows nothing of your array of structs.

When you call the function, you want to pass it one of the structs from your array which you do like this:

belowDayMin (grTEMPControl[HOT]);

Or more likely, since it has a boolean return value:

if(belowDayMin (grTEMPControl[HOT]))
  {
  // Do stuff
  }
else
  {
  // Do other stuff
  }

Hello all

I have done some reading on pass by value and pass by reference.

I was wondering. In my case, as I am only comparing the values and not really changing them is there a difference or preference which method should be used?

Thank you.

moses

From a purist coding perspective, if you don't intend to change anything in the structure you're passing, call by value is preferred. It will protect you from subtle bugs if you do change something but didn't intend the change to persist.

If the structure being passed is large however, you may want to pass it by reference for performance reasons. Using pass by value, the structure must be copied onto the stack, which will consume processor cycles.

In Arduino world, with limited RAM, it may be more important to save stack memory than to be a coding purist, so again, call by reference might be preferred for large structures.

wildbill: From a purist coding perspective, if you don't intend to change anything in the structure you're passing, call by value is preferred. It will protect you from subtle bugs if you do change something but didn't intend the change to persist.

If the structure being passed is large however, you may want to pass it by reference for performance reasons. Using pass by value, the structure must be copied onto the stack, which will consume processor cycles.

In Arduino world, with limited RAM, it may be more important to save stack memory than to be a coding purist, so again, call by reference might be preferred for large structures.

If your not changing the parameter in the function, passing by value and passing by constant reference should be optimized to be indistinguishable anyway. The compiler's usually not stupid.

Hello all

I have been using the above concept and it worked very nicely. Now I have a question whith relates to it.

I tried to write a second set of functions to decide what time of day it is through a RTC.

In one tab I have some code for the RTC and some structs. And in the second tab I have the functions of the time of day, which will be used later on.

This is the code for the functions:

bool ItsDawn(DateTime dateTimenow)
{
  return ( dateTimenow.hour() >= 8 && dateTimenow.minute() >= 0 dateTimenow.second() >= 0 );
}

bool ItsMorning(DateTime dateTimenow)
{
  return ( dateTimenow.hour() >= 8 && dateTimenow.minute() >= 0 dateTimenow.second() >= 0
          && dateTimenow.hour() < 10 && dateTimenow.minute() < 0 dateTimenow.second() < 0 );
}

bool ItsNoon()
{
  DateTime dateTimenow
  return ( dateTimenow.hour() >= 10 && dateTimenow.minute() >= 0 dateTimenow.second() >= 0
          && dateTimenow.hour() < 14 && dateTimenow.minute() < 0 dateTimenow.second() < 0 );
}

bool ItsAfternoon()
{
  DateTime dateTimenow
  return ( dateTimenow.hour() >= 14 && dateTimenow.minute() >= 0 dateTimenow.second() >= 0
          && dateTimenow.hour() < 20 && dateTimenow.minute() < 0 dateTimenow.second() < 0 );
}

As in the above idea I wanted to pass the time variable by value. Which gave the following error:

Arduino: 1.8.9 (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"

R:\Arduino\Terrarium\0_TerrariumSteuerung_PuttingItTogether_RTC_aktuellsten\a_Functions.ino: In function 'bool ItsDawn(DateTime)':

a_Functions:8:65: error: expected ')' before 'dateTimenow'

   return ( dateTimenow.hour() >= 8 && dateTimenow.minute() >= 0 dateTimenow.second() >= 0 );

                                                                 ^

R:\Arduino\Terrarium\0_TerrariumSteuerung_PuttingItTogether_RTC_aktuellsten\a_Functions.ino: At global scope:

a_Functions:11:27: error: expected primary-expression before 'dateTimenow'

 bool ItsMorning((DateTime dateTimenow))

                           ^

a_Functions:11:27: error: expected ')' before 'dateTimenow'

c_Test_Temp:258:1: error: expected ',' or ';' at end of input

 } // Test_Temp

 ^

exit status 1
expected ')' before 'dateTimenow'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

As you see in the functions 3 and 4 I took the pass by value statement out of the braquets and put it inside of the curly braquets, which didn’t give me an error message anymore.

Can anyone please tell me what the difference is and why one works while the other doesn’t?

I also had to add braquets for the comparison statements to prevent an ´;´ error. I would also be glad to know why this is necessary as it wasn’t in the previous functions.

Thank you.

moses

It’s nothing to do with pass by reference or value.

You’ve missed out a logical operator.
This:

( dateTimenow.hour() >= 8 && dateTimenow.minute() >= 0 dateTimenow.second() >= 0 );

Says hour greater than eight and minute greater than or equal to zero second greater than or equal to zero.

It makes no sense in English and it makes no sense in code. Add another &&.

Better, don’t. For something as imprecise as Is morning, is it really important what the value of seconds is?

wildbill:
From a purist coding perspective, if you don’t intend to change anything in the structure you’re passing, call by value is preferred.

That’s exactly the opposite of the truth.

With potentially “heavy” objects, like structs, passing by value is used only if you intend to change the data in the parameter, but don’t want this changes to affect the original argument. The proper C++ programming practice (extensible to C as well) says: Make a copy only if you need a copy. And if you do need it, let the compiler do it for you - pass by value, instead of copying it explicitly yourself.

If you don’t intent to change the passed object, you pass by const reference. Case in question

bool belowDayMin(const structTEMPControl &control)
{
  return control.value < control.minDay;
}

Not this (!!!)

bool belowDayMin(structTEMPControl control) // <- very bad!!!
{
  return control.value < control.minDay;
}

As usual, every rule has exceptions. If you know that the struct object is tiny and you really need to squeeze some bytes or CPU cycles from the code, passing by value might be acceptable. In this case it is not even remotely acceptable.

wildbill:
It will protect you from subtle bugs if you do change something but didn’t intend the change to persist.

Proper use of const qualifier is what protects you from “unintended modification” bugs. Not “passing by value”. “Passing by value” in this context is what actually promotes bugs by being excessively forgiving.

wildbill:
If the structure being passed is large however, you may want to pass it by reference for performance reasons. Using pass by value, the structure must be copied onto the stack, which will consume processor cycles.

In Arduino world, with limited RAM, it may be more important to save stack memory than to be a coding purist, so again, call by reference might be preferred for large structures.

Here we go. But still misleading. You don’t need to sacrifice purism to performance. Passing by const reference is what gives you both. Passing by const reference is “coding purism”.

There’s no “coding purism” is passing by value - unjustified copying is simply sloppy coding. Quite the opposite of “coding purism”.