To tab, library, or other?

I have looked for resources on tabs for making life easier in this environment. So far, none have really provided a rock solid defense on what to do, and how to do it. So, If I have a large file, should I parse everything below the loop into a .h tab, an .ino tab, or make a new library? Also, are there any examples on how to use either of the tab suggestions? All I have found is "Make a tab and call it or something in the global file, it's not that hard, just do it." Ok...I'll get right on that.

I have a large program that compiles fine, but as soon as I start putting my functions in new tabs, whether they are .h or .ino, the compiler starts freaking out. I am in a rut and can't climb out.

Thank you.

1 Like

Some of the following is duplicated from the reply Delta_G made while I was typing it but I'll post it anyway:

The reason to make a library is that you have code that you want to share between multiple projects.

When you want to make a large sketch easier navigate the easiest way to do it is by breaking it into multiple .ino tabs. The Arduino IDE automatically adds the .ino extension when you create a tab and do not specify a different valid extension. The only thing you need to remember is that all .ino tabs will be concatenated into one file in the order they are shown in the Arduino IDE (the file matching the sketch name followed by the rest in alphabetical order).

You also have the option of adding .h and .cpp files, etc. if you like. If you do that then you need to remember to include the .h files from your sketch and also that the Arduino IDE doesn't do the usual preprocessing magic on these files so you need to manually add:

  • #include <Arduino.h> if your code requires the use of the Arduino core library code.
  • Function prototypes
1 Like

Delta_G:
With .h you need a .cpp with the implementations in it.

Not actually true. I just put all my code in the .h files.

stevenette:
So, If I have a large file, should I parse everything below the loop into a .h tab, an .ino tab, or make a new library?

IMHO ...

I would only create a library if I needed to distribute the code in a convenient package for other users.

Also a library is really only suitable for code that is never likely to change because it is usually shared with different projects and if you alter the library for one project you can break another project. I don't reckon any of my code is ever finished :slight_smile: - even if some of my projects are. When I want to use code in a new project I just copy it from an older project.

The choice between using a .h file or ,ino files is probably a matter of personal preference. I think I took to using .h files when I wanted to share a file between two different programs - so it could not be in the directory for either project.

...R

1 Like

Still uncertain how to use multiple tabs ....

I use a lot of RemoteXY stuff, and when making changes, I have to copy the "RemoteXY Configurate" code from the designer website into my sketch, over-writing the previous version.

Up until now, I've just put this block of code in my sketch, and when I need to change it, I have to click/scroll the whole block in order to paste the new block in. That works fine, but now I'm thinking an easier way would be to have a separate tab for the RemoteXY config, then I can just Ctrl-A & Paste, to replace it.

This isn't a library file, it's just standard Arduino code that I want to include at the correct point in my main code.

Can't seem to find the correct syntax to get it included - please someone enlighten me ....

I have the RemoteXY code block in a new tab called "Remote_XY" (without the quotes), and in my main sketch I have tried all of the following...

#include <Remote_XY>
#include Remote_XY
#include "Remote_XY"
#include <Remote_XY.ino>
#include Remote_XY.ino
#include "Remote_XY.ino"

All of which generates the error "Remote_XY: No such file or directory".

If I try to rename the tab as "Remote_XY.ino", it tells me that that file already exists.

How do I get my code from the tab included ....

Having read this answer to someone else's question on the subject ...

"There is no need to use an #include directive for the additional .ino file.
Before compilation starts, the Arduino IDE concatenates all .ino files in your sketch into a single file, starting with the .ino file that matches the sketch folder name, followed by the rest of the .ino files in alphabetical order. So there is no difference between one massive .ino file and breaking the same code among multiple .ino files, other than the greater ease of navigating the code via tabs. After a bit more processing, this file is compiled as C++."

It appears as though I may be barking up the wrong tree.

Is there no way to include code from a separate tab at the correct place in your sketch ?

Robin2:
Not actually true. I just put all my code in the .h files.

And if I was code reviewing your work, I would ding you so hard your head would spin. :slight_smile:

This is bad form when doing c++ especial in a larger code base. Simple changes to code in a header will cause all other classes that include that header to require a recompile. In a large project this could significantly impact compile time.

I spent 2 weeks when I took over as Director Of Development, to have my staff correct this very exact thing in our code base.
IMHO there are only a few cases where implementation should or needs to be in the header.

Is there no way to include code from a separate tab at the correct place in your sketch ?

What, in your opinion, is the correct place ?

Can you put the code that you want to change in its own function and on its own tab in the IDE? If so, then within reason it won't matter where it is within the final code.

daba:
Is there no way to include code from a separate tab at the correct place in your sketch ?

Yes there is, but not if you use ino files.

A complete example would be:

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

#include "tab.hpp"

void loop() {
  tabFunction();
  delay(1000);
}
#pragma once

void tabFunction();
#include "tab.hpp"
#include <Arduino.h>

void tabFunction() {
  Serial.println(F("Hello World from tab!"));
}

Note the use of quotes for including the tabs, and angled brackets for the Arduino file. Quotes tell the preprocessor to look in the current folder for the file (and then in the library folders afterwards). Angled brackets tell the preprocessor to look in the library folders only, not in the current folder.


If you only want to insert some code, just use the header file (HPP), you don't need an implementation file (CPP) in that case.

Note that #including a file just copies and pastes the entire included file at the location of the #include statement.

Also keep in mind that you can't have multiple definitions. So either don't define anything in the header files (only declarations), or make sure that the header file is included only form a single CPP or INO file.

Sometimes, you can't have multiple declarations either, so you have to make sure a header file is only included once in each translation unit (CPP or INO file). Use #pragma once or include guards in your header files to solve this.

1 Like

UKHeliBob:
What, in your opinion, is the correct place ?

Can you put the code that you want to change in its own function and on its own tab in the IDE? If so, then within reason it won't matter where it is within the final code.

That really takes away the simplicity of copying the code block from the web-development platform in its entirety, and simply pasting it over ALL of the contents of that tab. If I then have to remake a function out of it, I'm gaining nothing.

According to RemoteXY instructions, this code block should precede void setup() and void loop(), but perhaps I'm stuck in old ways, having programmed (poorly) in BASIC so many years ago.

Here's what the block looks like, this is for a single pushbutton and 1 LED interface.....

/*
   -- Button_LED --
   
   This source code of graphical user interface 
   has been generated automatically by RemoteXY editor.
   To compile this code using RemoteXY library 2.3.5 or later version 
   download by link http://remotexy.com/en/library/
   To connect using RemoteXY mobile app by link http://remotexy.com/en/download/                   
     - for ANDROID 4.3.1 or later version;
     - for iOS 1.3.5 or later version;
    
   This source code is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.    
*/

//////////////////////////////////////////////
//        RemoteXY include library          //
//////////////////////////////////////////////

// RemoteXY select connection mode and include library 
#define REMOTEXY_MODE__SOFTSERIAL
#include <SoftwareSerial.h>

#include <RemoteXY.h>

// RemoteXY connection settings 
#define REMOTEXY_SERIAL_RX 2
#define REMOTEXY_SERIAL_TX 3
#define REMOTEXY_SERIAL_SPEED 9600


// RemoteXY configurate  
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =
  { 255,1,0,1,0,28,0,8,13,0,
  1,2,12,24,47,12,2,31,80,114,
  101,115,115,32,109,101,32,33,0,65,
  4,69,23,16,16 };
  
// this structure defines all the variables of your control interface 
struct {

    // input variable
  uint8_t button; // =1 if button pressed, else =0 

    // output variable
  uint8_t led_r; // =0..255 LED Red brightness 

    // other variable
  uint8_t connect_flag;  // =1 if wire connected, else =0 

} RemoteXY;
#pragma pack(pop)

/////////////////////////////////////////////
//           END RemoteXY include          //
/////////////////////////////////////////////



void setup() 
{
  RemoteXY_Init (); 
  
  
  // TODO you setup code
  
}

void loop() 
{ 
  RemoteXY_Handler ();
  
  
  // TODO you loop code
  // use the RemoteXY structure for data transfer


}

But I just extract the middle part, enclosed in all those /////'s, and paste it over the block that is already in my sketch. I thought I would be able to just put this on its own tab, and use some sort of include.

It's straightforward, click-drag the source from the web-page, Ctrl-C, click drag the block I want to replace in my sketch, Ctrl-V. Just thought I might be able to eliminate one of those click-drags with a Ctrl-A.

This configurate block can get quite large, so click-dragging and scrolling can take a few precious seonds....

PieterP:
Yes there is, but not if you use ino files.

A complete example would be:

void setup() {

Serial.begin(115200);
}

#include "tab.hpp"

void loop() {
  tabFunction();
  delay(1000);
}






#pragma once

void tabFunction();






#include "tab.hpp"
#include <Arduino.h>

void tabFunction() {
  Serial.println(F("Hello World from tab!"));
}




Note the use of quotes for including the tabs, and angled brackets for the Arduino file. Quotes tell the preprocessor to look in the current folder for the file (and then in the library folders afterwards). Angled brackets tell the preprocessor to look in the library folders only, not in the current folder.



---



If you only want to insert some code, just use the header file (HPP), you don't need an implementation file (CPP) in that case.

Note that #including a file just copies and pastes the entire included file at the location of the #include statement.

Also keep in mind that you can't have multiple definitions. So either don't define anything in the header files (only declarations), or make sure that the header file is included only form a single CPP or INO file.

Sometimes, you can't have multiple declarations either, so you have to make sure a header file is only included once in each translation unit (CPP or INO file). Use #pragma once or include guards in your header files to solve this.

Not sure if I understand that completely PieterP....

Let's break it down ....

At the top of my sketch I can have a largish "section" of code (The RemoteXY Configuration block), that I will develop sequentially throughout the development of my sketch, so I need to be able to replace it quickly.

If I put that block in a separate tab, called "Remote_XY", for example, can I then use ... ?

#include "tab.Remote_XY"

But what makes the block of code an hpp file ?

It's got me a bit confused, to be honest....

You just add a new tab, and name it "Remote_XY.hpp".
Then you paste your block of code in that file.
In the main .ino file, you just add #include "Remote_XY.hpp".

HPP is the extension for C++ Header files, it's nothing special.

PieterP:
You just add a new tab, and name it "Remote_XY.hpp".
Then you paste your block of code in that file.
In the main .ino file, you just add #include "Remote_XY.hpp".

HPP is the extension for C++ Header files, it's nothing special.

I have tried exactly that, extracted the code I continually update into a new tab called "Remote_XY.hpp", and put #include "Remote_XY.hpp" in the ino sketch.

I get the error message ...

"open C:\Users\Dave\AppData\Local\Temp\arduino_build_367997\sketch\pRojeCt_BEAT.ino.cpp: Access is denied.
Error compiling for board Teensy 3.2 / 3.1.
"

It compiled fine before moving the block into the new tab ....

This error has to do with Windows' file permissions, not with Arduino.

Does creating a new sketch from scratch work?

PieterP:
This error has to do with Windows' file permissions, not with Arduino.

Does creating a new sketch from scratch work?

I will try tomorrow, on my way out to eat now, then going to see a band...

daba:
I will try tomorrow, on my way out to eat now, then going to see a band...

Thought I'd have a quick look, was able to open all folders down that path until the "sketch" folder. I tried to "Take Ownership", but it still would not let me access it.

I am an administrator on this PC (Windows 7 Pro), but it won't let me in to change any permissions... odd

This sort of error could be caused by your antivirus software. Try TEMPORARILY disabling your antivirus for a single compilation to see if the problem goes away, then turn the antivirus back on. If the problem doesn't occur with the antivirus off you will need to adjust the settings of your antivirus to whitelist the appropriate file, folder, or process so it doesn't interfere with compilation.

pert:
This sort of error could be caused by your antivirus software. Try TEMPORARILY disabling your antivirus for a single compilation to see if the problem goes away, then turn the antivirus back on. If the problem doesn't occur with the antivirus off you will need to adjust the settings of your antivirus to whitelist the appropriate file, folder, or process so it doesn't interfere with compilation.

That could well be the reason, I will try it out.

I have had lots of troubles with my Anti-Virus software, I won't name and shame, but at each upgrade they add new "features", which inevitably cause some problems along the way.

What I did discover though, is that it is the IDE that creates that folder, and removes it when it closes the sketch. If it has the power to delete it, how come it can't access it ? hmmmm, interesting question that..

daba:
That could well be the reason, I will try it out.

Well it compiled nicely with AVG turned off, so I closed the IDE, re-enabled AVG, and tried compiling again.

Was a little surprised to see that it compiled without errors......

daba:
Well it compiled nicely with AVG turned off, so I closed the IDE, re-enabled AVG, and tried compiling again.

Was a little surprised to see that it compiled without errors......

The more I think about this, the more I believe it to be an error caused by the IDE, not by my system or A/V software.

The path in question was ...

"C:\Users\Dave\AppData\Local\Temp\arduino_build_367997\sketch\pRojeCt_BEAT.ino.cpp"

Now, "C:\Users\Dave\AppData\Local" is a persistent location, and what follows it is a Temp folder created by the IDE, which it then deletes on exit.

If the IDE had created a folder that it needed access to, and didn't set the attributes of it, and its sub-folders correctly, that would be a bit dumb, to say the least.

I have just re-checked with Windows Explorer, and I can access all the way down into the furthest parts of the path (with the sketch open in the IDE), which I wasn't able to do yesterday ....