Reference code in main.ino from module?

If I create a project named MyProject.ino, the .ino is where the main code is written.

If I create a module or second tab with additional code, I may create the following:

ExtraFunctions.cpp
ExtraFunctions.hpp

At the top of MyProject.ino I do:

#include "ExtraFunctions.hpp"

This allows calling functions in the ExtraFunctions module from the main MyProject.ino

However, how do you go the other direction? If I want to reference a function or variable or object from the ExtraFunctions module that exists in MyProject.ino, it should work if I #include a reference to MyProject.ino in ExtraFunctions, but I don’t know how to do that as MyProject.ino doesn’t have a header.

I understand this may be bad practice, so I can possibly include the items from MyProject in the ExtraFunctions module, though I haven’t been able to do this with Timer.

I have tried adding the Timer object to the .hpp header in the module ExtraFunctions.hpp like this:

Timer tmr_1minute(60000, tmr_1minute_service);

The callback tmr_1minute_service exists in ExtraFunctions.cpp with the declaration in ExtraFunctions.hpp

I attempt to start this timer from setup() in the main MyProject.ino like this:

tmr_1minute.start();

But I get compile errors:

multiple definition of `tmr_1minute'

I have run into essentially the same problem with any objects being created in Particle, which forces me to add a lot of code to the main MyProjrect.ino when I would rather put it in separate files.

The easiest way to share global objects between modules would be to use the extern keyword.

More explanation here:

Hmm…

I do use extern when declaring variables in the external modules, but I’ve never tried extern in the main MyProject.ino

I just tried adding this to MyProject.ino:

extern Timer tmr_1minute(60000, tmr_1minute_service);

However, when I call tmr_1minute.start(); from my ExtraFunctions.cpp, I still get errors pointing to where I called the start():

'tmr_1hour' was not declared in this scope
     tmr_1hour.start();

So it’s like the code in the module can’t see the code in the main MyProject.ino file.

The only way I have found to get around this problem is to create object in the .cpp of the extra module, then only interact with that object from within the extra module (or another 3rd module works also if I include the .hpp of the first module), but then I can’t call that object at all from the main MyProject.ino, so I have to put a wrapper function in ExtraFunctions.cpp that deals with the object, then I call that wrapper from MyProject.ino.

extern means “somewhere else” irrespective whether used in a “main” module (which isn’t really a thing - all modules are equal, only one of them holds the entry point function).

You just slapped the extern keyword in front of a definition but externs are merely place holders for a variable that is defined somewhere else. You cannot use a specific constructor as this would create an instance that will most likely not fit the one central definition located somewhere else.

If you want to use tmr_1minute inside your ExtraFunctions module you need to have an extern Timer tmr_1minute; declaration in that module where you want to use it.

To sum this up, you can put this in all your files that want to use that timer (or implement it)

extern Timer tmr_1minute;

Then you can put your actual instantiation of the timer in one of them along side the implementation of void tmr_1minute_service().

However, it’s not considered good style to scatter interdependent functions and variables over multiple modules. What belongs togehter should be kept together. When one module needs to interact with another it’s typically better to have well defined interfaces between the two (which can then broken out and shared via header files).

BTW

You can simply add a MyProject.h file and put the definitions into that :wink:

2 Likes

Thank you that was very helpful.

1 Like