Using #define to on and off functions

Hello Friends,
I have created configuration.h file, where I want to run or don't run some functions in the sketch. For example
#define motor_direction 0 // if 0 clockwise, if 1 counterclockwise.
I can do this way:
if(motor_direction == 0)
clockwise();
if(motor_direction == 1)
counterclockwise();

But I believe it must be something like this
#if def motor_direction = 0
clockwise();
#endif

But how correctly?
Thanks!

if this is that simple and just a function call, you could do:

in your config.h file

// comment out the one you don't want
#define runMotor clockwise
//#define runMotor counterclockwise

in your code

#include "config.h"
...

  runMotor();

the text runMotor will be textually replaced by whatever you wrote in the .h by the preprocessor and so the right function will end up being called.

1 Like

https://en.cppreference.com/w/cpp/preprocessor

#if motor_direction == 0
clockwise();
#elif motor_direction == 1
anticlockwise();
#else
#error "Invalid motor_direction setting!"
#endif

Note that final else to catch an invalid definition of motor_direction

Note that this all happens at compile time - so you would have to rebuild and reload the sketch to change the motor direction.

Note that it's conventional to use ALL_UPPERCASE names for #defined symbols - so distinguish them from actual program variables.

an example

It depends on how you want the code to be handled at runtime. Both will work.

With the if test, the compiled code will have the if, the else, and both function calls. This is going to make the code a little bigger than it needs to be.

By using ifdef you are doing conditional compilation. That means that the end code going to the compiler has EITHER one function or the other. Whichever one is not being used us just cut out and there is no call there for it. There is also no code for if or else. That means that the end code is a little bit smaller. It might also mean a tiny bit faster except that I bet the compiler recognizes all of this and optimizes it anyway.

This would work, but isn't terribly readable once that #define gets far away from the calling code. If I wanted this answer I'd make the function call real and conditionally compile the inside.

So instead of having a clockise() and counterclockwise as separate functions, you'd just have one function:

void runMotor(){

#ifdef CLOCKWISE
    
           // Here goes the code that runs clockwise

#endif
#ifdef COUNTERCLOCKWISE


         // Here goes the code that runs counterclockwise

#endif
}

and the calling code just calls runMotor and runMotor will have whichever code is needed inside. This last option creates the smallest code (barring compiler optimizations). But it does preclude you from using both functions in the same code at a later time.

1 Like

Thank you very much for fast replay!
One more question, how it works if;
#define sensor 2 // 1 - GPS, 2 - COMPASS, 3 - TEMPERATURE

void sensor_work()
{

analogRead(GPS);

analogRead(COMPASS);

analogRead(TEMPERATURE);

}

That doesn't make sense. I don't think it compiles. None of GPS, COMPASS or is defined

This is my personal opinion, but I consider #define/#ifdef to be a necessary evil to be avoided as much as possible.

In your case, I would make motor_direction a constant.

const int motor_direction = 1;

No. The compiler evaluates all constant conditions at compile time and omits all false branches. IMO this happens already at the lowest optimization level.

A better approach would be

enum INPUTS {GPS=1, COMPASS, TEMPERATURE};
...
analogRead(GPS);

analogRead(COMPASS);

analogRead(TEMPERATURE);

Normally the benefit of using an enumeration instead of a #define is that you get compiler checking of types and it reduces the errors you could make. In this case you don't get that because the parameter type to analogRead(x) is an int, but it makes for more readable code.

1 Like

So now in my configuration.h file I have:

sensor_type 2 // 1 - sensor A, 2 - sensor B, 3 - sensor C

in main file I have:

void sensors()
{
/// IF Sensor A run only this part

a = analogRead(A0);
output = map(a, 0, 100, 0, 10);

////END

/// IF Sensor B run only this part

b = analogRead(A1);
output = map(b, 0, 1000, 0, 10);

////END

/// IF Sensor C run only this part

c = analogRead(A0);
output = map(c, 0, 2000, 0, 10);

////END

}

what is the best way in my case?
Thank you all for leaving me an answer!

Please help us keep the forum tidy…

Edit your post using the :pencil2: in the tool bar just below your post

select the code part and press the <code/> icon in the tool bar to mark it as code. (also make sure you indented the code in the IDE before copying, that’s done by pressing ctrlT on a PC or cmdT on a Mac)

➜ do yourself a favour and please read How to get the best out of this forum

2 Likes

And don't ask questions about code that clearly will not compile, please.

well that's his question - how to write that code with #ifdef or #if I suppose

but without code tags even for pseudo code, I'm out

Thanks guys! I get it!

#include "config.h"

void setup() {
  Serial.begin(115200); Serial.println();
}

void loop() {
  stop();
}

void STOPPWM() {Serial.println("SOFT STOP");}
void STOP() {Serial.println("NORMAL STOP");}
 

and here my define file:

// comment out the one you don't want
//#define stop STOPPWM
#define stop STOP

#if !defined(stop)
#error You need to pick one
#endif

Now the question is it correct way if I add more defines? For example:
#define turn_left SOFT_START
#define turn_left NORMAL_START

Should I just add in define.h like this?

//#define turn_left SOFT_START
#define turn_left NORMAL_START

#if !defined(turn_left)
#error You need to pick one
#endif

// comment out the one you don't want
//#define stop STOPPWM
#define stop STOP

#if !defined(stop)
#error You need to pick one
#endif

Thank you very much! This define option allows me to change things in my code very fast and easy! I am really very happy!

And one more question.. if I look at this code at first time, how do I know that void STOPPWM(); "belongs" to stop(); ?

#include "config.h"

void setup() {
  Serial.begin(115200); Serial.println();
}

void loop() {
  stop();
}

void STOPPWM() {Serial.println("SOFT STOP");}

void STOP() {Serial.println("NORMAL STOP");}

You don't. That's why I suggested doing something different at the end of reply #5. Use a function name that makes sense either way, and make the guts of that function conditional. That way if someone needs to go look up what the function does, they can find it.

If I was trying to debug your code, I'd hunt for the stop() function for a while and give up and send it back. If stop() was a normal function with many different sections, it would be complicated, but at least I would be able to find and understand it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.