Overiding #define

One of the libraries I use is the Servo.h library. It defines a default pulse width used on startup.

#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
I’d like to change this but I don’t want to create a non standard library. Is there any way the program can redefine DEFAULT_PULSE_WIDTH?
Regards
Dave

You can do a "write" before the "attach".

Thanks AWOL, that answers my specific case, but I'd also be interested to know in the more general case if #Defines can be redefined Dave

Just put another #define after it, will change what was defined before.

michinyon: Just put another #define after it, will change what was defined before.

So if the library has

define DEFAULT_PULSE_WIDTH 1500

I can write

define DEFAULT_PULSE_WIDTH some_other-value

in the program that uses the library?

They can be “un defined” then re defined :

#include <lib_that_defines_DEFAULT_PULSE_WIDTH.h>
#undef DEFAULT_PULSE_WIDTH
#define DEFAULT_PULSE_WIDTH <whatever value you want>

Brilliant! Thanks

But unless you change the .h file it won’t do you any good!

Mark

holmes4: But unless you change the .h file it won't do you any good!

Mark

Why would you have to change the .h file? Are you saying that @tammytams method doesn't work? Why not?

  1. the IDE re-writes the .ino to turn it into a .cpp file.

  2. gcc processes (and all other c compilers) processes each .c/.cpp file as an individual creating a .o file for each .c/.cpp file The .o files are then linked.

3 #defines do NOT carry over between compilation units (.c/.cpp files )

The redefinition only works with in the file in which it is made.

It will not be used when servo.cpp is built!

Mark

Only one way to resolve this, try it. Sorry tammytam your method didn't work. Dave

No it won't for this situation, as Holmes has already explained, #defines are set per .cpp. or more strictly they are set until they are set again, so can be set multiple times within a .cpp.

In your situation, the define is set in servo.h, your .ino includes this file, and so your define is set to whatever it sets it to.

If you undef and def it within your .ino, the pre processor will replace any instances with your value in your .ino only, the pre processor has already replaced any instance of it in servo.cpp with the value from servo.h.

Your only solution is to overide the value by changing the define, or change the code to accept setters and getters for it. #defines are generally meant to be constants however :)

Well there was always the hope!

tammytam: snip Your only solution is to overide the value by changing the define, or change the code to accept setters and getters for it. #defines are generally meant to be constants however :)

What the H*** are setters and getters. Just the same I don't want to change published libraries. Perhaps the author would like to do an update with the ability to change the default, just as the default min and max are selectable by the calling program. I don't have the capacity, my 70 year old brain has only been doing C++/Arduino for a couple of months! Dave

Getters and setters are accessor methods used to control access to the normally private class data members. A getter will normally simply return its associated member, whereas a setter will normally vet any values passed to it, before setting the data member.

AWOL: Getters and setters are accessor methods used to control access to the normally private class data members. A getter will normally simply return its associated member, whereas a setter will normally vet any values passed to it, before setting the data member.

Forget I asked, 'accessor methods used to control access to the normally private class data members.' Two terms that mean nothing to me. Likewise 'associated member' and 'data member'. Looks like it would need more than a few lines to explain it. Thanks just the same Dave

(simplified) A class like the Servo class has public members which any can access, and private members which can only be accessed by the class itself. (strictly speaking, only an object, which is an instance of the class can access them). The reason for this is encapsulation - if anyone were able to change the value of a data member of a class, then the class wouldn't easily be able to maintain its integrity, because anyone could change its internal state at any time.

An accessor (setter or getter) is a public function in the class, and because it is a member, it has read/write access to the private data members. A setter normally needs to vet any values passed to it, to ensure that the range of the value passed to it doesn't cause the class/object to break, and also has to modify any other parts of the class/object that are dependent upon the changed value.

Thanks AWOL, that now makes sense, due to the fact that OOB and classes are familiar to me via my Pascal background. Dave

Some code to go with AWOLs description:

class Person
{
public:
	Person(){};
	~Person(){};

	int get_age( void ) { return age; };		// a getter, gets age
	void set_age( int age ) { m_age = age; };	// a setter, sets age

private:

	int m_age;	// Can't access this directly, its private!
};

void loop()
{
	Person Fred;
	//Fred.m_age = 10;				// This won't work, won't compile
	Fred.set_age( 10 );				// This will work
	//int fred_age = Fred.m_age;	// This won't work, won't compile
	int fred_age = Fred.get_age();	// Again, this will work
}

Hmmm

tammytam:
Your only solution is to overide the value by changing the define, or change the code to accept setters and getters for it.

Smells like a challenge to me!

This should work on an UNO, you’ll have to add in weak vector declarations for the Mega timers (error in source will show which ones.) Only tested compiling on 1.5.7 and 1.6.6.

namespace CustomServo{
  SIGNAL (TIMER1_COMPA_vect) __attribute__((weak)); //To allow our local .cpp to override lib .cpp
  #include <Servo.h>
  #undef DEFAULT_PULSE_WIDTH
  #define DEFAULT_PULSE_WIDTH 3000
  #include <avr\Servo.cpp>
};
typedef CustomServo::Servo Servo;

//Then as normal
Servo myServo;

void setup() {}

void loop() {}

pYro_65:
Hmmm
Smells like a challenge to me!

This should work on an UNO, you’ll have to add in weak vector declarations for the Mega timers (error in source will show which ones.) Only tested compiling on 1.5.7 and 1.6.6.

namespace CustomServo{

SIGNAL (TIMER1_COMPA_vect) attribute((weak)); //To allow our local .cpp to override lib .cpp
  #include <Servo.h>
  #undef DEFAULT_PULSE_WIDTH
  #define DEFAULT_PULSE_WIDTH 3000
  #include <avr\Servo.cpp>
};
typedef CustomServo::Servo Servo;

//Then as normal
Servo myServo;

void setup() {}

void loop() {}

I like it :slight_smile: