functions ahead of setup() and loop()

I think it's okay to put my functions at the top of the sketch before setup(). I see other people's sketches doing that.

However, can I put those functions into individual tabs still located at the top of the sketch (left side tabs)? And then use seperate right-side tabs for setup() and loop()?

One minor problem seems to be the label of the left most tab is forced to reflect the sketch file name. I can live with that inconvenience, but are there other less-obvious drawbacks?

I'm trying to accomplish two things.

  1. Keep global variables associated with my functions in the same area as the function. If my functions are at the bottom of the sketch then their associated global variables have to be at the top of the sketch. That seems unorganized to me. Ditto for related "#include" statements.

  2. Make my functions easily movable to other sketches by just copying the tabs.

Thanks, Frank

Tabs:

frank2644:
I think it's okay to put my functions at the top of the sketch before setup(). I see other people's sketches doing that.

Yes. You can order them however you like.

frank2644:
However, can I put those functions into individual tabs still located at the top of the sketch (left side tabs)? And then use seperate right-side tabs for setup() and loop()?

Yes

frank2644:
2) Make my functions easily movable to other sketches by just copying the tabs.

That's what libraries are for. No copying necessary and when you make an improvement to the function in the library it applies to all sketches that use the library instead of having to go make the same change in a bunch of places.
https://www.arduino.cc/en/Hacking/libraryTutorial

Wow, thanks for all the fast and helpful responses.

Definitely answered my questions and then some.

Frank

If a function is declared below "loop()" it can actually not be called from "loop()" unless a function prototype is declared before "loop()". The Arduino IDE automatically declares these prototypes along with adding some includes to your sketch before it is actually compiled. You can try to find your sketch in the temporary folder created by the Arduino IDE to see the full content. Declaring your function above "loop()" will avoid the need of a prototype.

void myFunction(int arg); //This is a prototype with no body

void loop()
{
  myFunction(1);
}

void myFunction(int arg)
{
  //This is the actual function with its body
  Serial.println(arg);
}

In the end it does not matter at all whether you move the body to where the prototype is or just leave it as is - whatever you like will do :slight_smile:

Danois90:
If a function is declared below "loop()" it can actually not be called from "loop()" unless a function prototype is declared before "loop()". The Arduino IDE automatically declares these prototypes along with adding some includes to your sketch before it is actually compiled. You can try to find your sketch in the temporary folder created by the Arduino IDE to see the full content. Declaring your function above "loop()" will avoid the need of a prototype.

void myFunction(int arg); //This is a prototype with no body

void loop()
{
 myFunction(1);
}

void myFunction(int arg)
{
 //This is the actual function with its body
 Serial.println(arg);
}




In the end it does not matter at all whether you move the body to where the prototype is or just leave it as is - whatever you like will do :)

I'm kinda weak on C++ programming so I may be missing something, but I think I have lots of working sketches where my functions are defined at the end of the sketch without using prototypes.

To be sure, I just modified the famous blink sketch by moving it's loop code to a function at the end and substituting a call to that function. Seems to work okay.

Hopefully, I have some clue about what I am doing, but maybe not.

Frank

frank2644:
I'm kinda weak on C++ programming so I may be missing something, but I think I have lots of working sketches where my functions are defined at the end of the sketch without using prototypes.

To be sure, I just modified the famous blink sketch by moving it's loop code to a function at the end and substituting a call to that function. Seems to work okay.

Hopefully, I have some clue about what I am doing, but maybe not.

Frank

Re-read the second sentence of the previous reply.

This is one of those areas where the Arduino environment helps, but veers aeway from standards.

In the 'real' C world, function prototypes are needed if the function code is contained in an 'external' file - added with an #incluide directive.

When you extebnd this logic, the 'uniformity of c-style lanhguages'' starts to appear.... functions and variables etc are all handled in the same way when the compiler goes to work/

You could declare

extern returnType myFunction(var0, var1;
just as easily as
extern varType myVariable;

The compiler will expect those elements to be declared elsewhere in one of the #included source files.
If not - an error will be thrown.
More here

Thanks, again, everyone.

I need to study some of the links provided and re-read some of the posts to really get a complete understanding..But I am definitely a little bit more knowledgeable now.

Frank

frank2644:
However, can I put those functions into individual tabs still located at the top of the sketch (left side tabs)? And then use seperate right-side tabs for setup() and loop()?

Yes. The other tabs are separate files. There are a few things that are important, however.

The other tabs should have a “.cpp” extension rather than a “.ino”. An arduino sketch should contain only one .ino file.

The other .cpp files will need to have this:

#include <Arduino.h>

at the top. This is done automatically for the .ino file, but the .cpp files will need to have it explicitly.

Most importantly: each tab is compiled separately from all the others. The main .ino file won’t know about the functions and variables in the other .cpp file and won’t be able to call them. To fix this, you normally crate a pair of files, one .cpp and one .hpp . the ‘h’ stands for header.

----- MySketch.ino ----

#include "MyFunctions.hpp"

void setup() {
  Serial.begin(9600);
  foo();
}
void loop() {}

----- MyFunctions.hpp ----

void foo();

----- MyFunctions.cpp ----

#include <Arduino.h>
void foo() {
  Serial.println("Foo!");
}

Note the difference between angle brackets and quotes in the #include directive. Quotes mean that the compiler should look for the include file in the sketch directory. Angle brackets mean that it should look for them in the library packages directory.

PaulMurrayCbr:
The other tabs should have a ".cpp" extension rather than a ".ino". An arduino sketch should contain only one .ino file.

Why do you say that?

pert:
Why do you say that?

That's the way the IDE works. .ino files are special - they are specially processed and their name should match the name of the directory the sketch is in. If you have a sketch directory HOME/Documents/Arduino/MySketch , there can only be one file there named MySketch.ino. Having more than one .ino can make the IDE do weird things with function prototyping, and I'd guess that it comes down to which .ino file is the 'first' one in the directory, by name or by date.

No, the way the Arduino IDE works is you can have as many .ino files as you like. Each .ino file appears as a tab in the Arduino IDE. During sketch preprocessing they will be concatenated starting with the one that matches the folder name, followed by the rest in alphabetical order. It won't make the IDE do anything weird with function prototyping. There's absolutely no difference between the code being all in one .ino file or broken up between multiple. It's just a way to make it easier to navigate large sketches.