Conditional inclusion problem (#ifdef)

Hello,

I usually create define based inclusion(s) in my sketches, but now I'm stuck with this one.

#define EXT_PIR_SENSOR

#ifdef EXT_PIR_SENSOR
const uint8_t PIR_SENSOR_PIN = A12;
const unsigned int PIR_THRESHOLD_RAW = 410u;
#endif

void setup()
{
  analogReference(DEFAULT);
}

void loop()
{

#ifdef EXT_PIR_SENSOR
  managePirSensor();
#endif
}

void managePirSensor()
{
  int pirValue = 0;
  pirValue = analogRead(PIR_SENSOR_PIN);
  if (pirValue >= PIR_THRESHOLD_RAW)
  {
    //do something
  }
}

If EXT_PIR_SENSOR is defined, the sketch compiles. But if I remove it, the compiler misses PIR_SENSOR_PIN and PIR_THRESHOLD_RAW from managePirSensor() function. This function should not be called at all! Even if I comment it in the loop, the error is still there. It drives me crazy. :upside_down_face:

Could someone help me out?

This method used to work in my sketches. It is convenient for me to create "options" in the sketch (for example printing to serial monitor during testing and simply remove the define if printing is not needed).

Thanks in advance.

#ifdef EXT_PIR_SENSOR
  managePirSensor();
#endif
}
#ifdef EXT_PIR_SENSOR
void managePirSensor()
{
  int pirValue = 0;
  pirValue = analogRead(PIR_SENSOR_PIN);
  if (pirValue >= PIR_THRESHOLD_RAW)
  {
    //do something
  }
}
#endif

It's nothing to do with being called, you defined it, and compiler tried to compile it

Tu en es sûr?

Why not condition the function itself?

Even it if should be optimised away, it still would have to be correct and compile… which is why I doubt it ever worked exactly like that.

a7

Oooh my bad. :zipper_mouth_face:

You are all right, I used to condition the function itself also.

Thanks for the quick help!

By the way, if defines already came up. :slight_smile:

Could someone tell me where these A0, A1, A2, etc. defines are?
I searched the C:\Program Files (x86)\Arduino\hardware\arduino\avr\ directory but couldn't find it.

Search wider or better!

I found

pins_arduino.h (6.3 KB)

in

Arduino.app/Contents/Java/portable/packages/arduino/hardware/avr/1.8.2/variants/standard

searching for A0, which turnt up a bunch of stuff, scanned that by eye.

a7

Nice, thank you @Coding_Badly and @alto777.

Now I know where did I miss it...I searched for "#define A12"...

Yeah, it's a tradeoff. I just searched for "A0" , took two refinements to narrow in.

If you had been lucky, it would have turned up in dozens of files (only). As it was even so much as a space between the '#' and the 'd' woulda left you with nothing.

Of course it should just be a matter of selecting it in you sketch and using the "Find Declaration" option in the Search sub menu. :expressionless:

a7

Of course it should just be a matter of selecting it in you sketch and using the "Find Declaration" option in the Search sub menu.

Which will be implemented...when exactly? :slight_smile:

Someone here could probably name a modern IDE or two that already have such a feature.

Maybe there's one that would be able to do Arduino tool chain builds. :expressionless:

a7

There is no harm in opening an INO file in notepad++ to execute that, and then to save and open it in the IDE
Actually the easiest would be a 'use external editor' preference.

Slobber/ Eclipse

Yeah, I usually use np++ for editing. It's soo much faster.

Another question came up. Is it okay to use a define for inclusion and use its value at the same time?

For example:

#define MONTH_FOR_SENSOR_LOGGING (11)

#ifdef MONTH_FOR_SENSOR_LOGGING
    if (dateTime.Month == MONTH_FOR_SENSOR_LOGGING)
    {
      sensorLogging = true;
    }
    else
    {
      sensorLogging = false;
    }
#endif

Why write one line, when eight will do the same job? :smiley:

sensorLogging = dateTime.Month == MONTH_FOR_SENSOR_LOGGING;

Good point. :slight_smile:

Should the defined number be casted for any reason or it is unnecessary?

For example:

#define MONTH_FOR_SENSOR_LOGGING ((uint8_t)11)

Under the right circumstances the compiler will generate less code. If the goal is to reduce Flash consumption then casting is helpful.

When concerned about the datatype make it a typed constant...

const uint8_t MONTH_FOR_SENSOR_LOGGING = 11;

The defined number is a 'literal' that means that it will just be copied into the code instead of the word.
So it depends what you want to use it for.
in this statement

if (dateTime.Month == MONTH_FOR_SENSOR_LOGGING))

It will be read as

if (dateTime.Month == (11))

I don't see any purpose in casting the '11' from 'int' (16-bit signed on an AVR) to uint8_t
When used in calculation, it can serve a purpose if you want to make sure that the calculation is done in 8-bit if all other variables in the calculation are 8-bit as well.
More important is to make sure that any value that is outside of the 16-bit integer range is specified as such

#define BAUD 250000UL

When concerned about the datatype make it a typed constant...

Yes, I always use constants if it's just a number. But this time I'd like to use it for conditional inclusion at the same time (#15). So my idea was to make things simple, if it is defined compile certain part of the code and use the defined value at the same time.

@Deva_Rishi Thanks for the tips. I think I'll go with the casting, because the dateTime.Month is an uint8_t variable in the struct.