I'm writing a library to bundle the wifi/MQTT connections into a reusable space, however I'm now thinking that as all the modules will be based on the same chip is it worth bundling the various classes and functions that will drive the motors/servos into the same library or a different one?
I'm wondering if it's worth splitting SignalControl and LEDControl out into their own separate libraries, or at least into dedicated files given that "controller.h" is now well over 500 lines long, but I'm not sure how I'd best do that in this language!
You appear to have a single header file which is used by very varied functions. For example WiFiSetupAndControl() and LEDControl(). More usual is that these would each have their own program (.cpp) and header file (.h).
A class model is useful but C++ also has a namespace model for encapsulation. For the case where you define a class and only ever create one instance of it, a namespace is a valid alternative to a class construct. It is the "why create a cookie cutter and make only one cookie" argument. For Arduino programming, I use a namespace model which someone ( I forget who ) published here on this site. That is each namespace has its own setup() and loop() method and this can make a very clean sketch. Where you need to create multiple instances of something, say buttons on a touch screen or queues etc., then you really need a class construct.
proffalken:
I'm writing a library to bundle the wifi/MQTT connections into a reusable space, however I'm now thinking that as all the modules will be based on the same chip is it worth bundling the various classes and functions that will drive the motors/servos into the same library or a different one?
I suggest separating your ideas about classes from your ideas about separate files. My approach had been to put a certain category of functionality into .h file (I'm a reluctant C++ programmer, I never bother with .cpp files, and the compiler doesn't care). For example for my model train wireless control project I have files called trainWirelessControl.h and turnoutControl.h. I also have a file called dataStructs.h as I found it easier to have all of them in one place because some of the data elements are common.
Quite separately, I would be very interested if you could provide an overview of the functionality of your project and its communication system. My goal is to have a layout that is entirely automated with the primary control in the hands of a Python program. My Arduino Mega just deals with the hardware (turnouts and LDRs) and nRF24 wireless communication with the trains based on instructions from Python.
@6v6gt: Could you post a skeletal example of this technique? I've often run into the situation where I define a class and then only instantiate one object of that class. To put your metaphor another way -- you shouldn't have to build a bridge just to cross a stream once.
Each module has a .h file and a .cpp file. The .h file contains the module's interface -- i.e. only the information that other modules need to use this module's public functionality. After the #include guards, this typically means:
The .h file may also contain class method implementations within the class declaration - but only if said implementations are short (couple of lines). It should also contain #include directives of any .h files needed by the contained declarations or by modules that use the interface. If there are any .h files only required by the implementations, then they should NOT be #included in the .h file but in the .cpp file.
Not only does this method provide superior modularity, but it allows you to take advantage of file-level scope control using the 'static' directive. This lets you keep functions and global variables private to the implementation file if other modules have no need for them.
gfvalvo:
@6v6gt: Could you post a skeletal example of this technique? I've often run into the situation where I define a class and then only instantiate one object of that class. To put your metaphor another way -- you shouldn't have to build a bridge just to cross a stream once.
Robin2:
Quite separately, I would be very interested if you could provide an overview of the functionality of your project and its communication system. My goal is to have a layout that is entirely automated with the primary control in the hands of a Python program. My Arduino Mega just deals with the hardware (turnouts and LDRs) and nRF24 wireless communication with the trains based on instructions from Python.
I use Eclipse / Sloeber for all my serious development work. Since I'm the only one writing code for my projects, I simply test as I go, sometimes creating simple temporary projects to test various modules.
gfvalvo:
I use Eclipse / Sloeber for all my serious development work. Since I'm the only one writing code for my projects, I simply test as I go, sometimes creating simple temporary projects to test various modules.
Fair enough, I've spent the last 10 years as a "DevOps Consultant" and I'm trying to bring automated testing into projects I do outside work as well - I'm tempted to do the same with this code just to see if I can!
Most Arduino projects, and especially the ones you see here where people are asking for help, tend to be very small. Unit tests are probably overkill. However, just like source code control, they can prove their worth even on a tiny project.
wildbill:
Most Arduino projects, and especially the ones you see here where people are asking for help, tend to be very small. Unit tests are probably overkill. However, just like source code control, they can prove their worth even on a tiny project.
Yeah, in 10 years of mucking about with this kind of stuff, this is the first project that's made me think "I could do with my own library here...", and from there everything's just spiralled into a "proper" project like I'd do at work!
I have a Bronze award from the N Gauge Society (in 2013) for an N-Gauge Farish large prairie that I converted to battery powered radio control using Deltang wireless gear that I re-programmed with the Arduino IDE. I also converted a couple of other locos but I have given up on N-Gauge because I find it visually too small - the trains seem too far away. I am working with 009 now as my space for a layout is too limited for 00 Gauge or H0.
It depends on your goals. How much code do you want to share with other people? That does in a library (.cpp and .h file with classes, usually). How much code do you want to use in other projects, by copying files? That code would go in a .cpp (not .c, unless you are a masochist) file, with corresponding .h file, without the use of classes. If none of code will be reusable, it all goes in the .ino file (there can be more than one; the IDE will combine them all).
Also I tend to take "black box" things that could be used elsewhere and turn them into small libraries. That way debugging a library (eg. a communications protocol, regular expression parser, LCD output) is done as a first step, and then the "main project" consists of assembling already-debugged parts.
Also I tend to take "black box" things that could be used elsewhere and turn them into small libraries. That way debugging a library (eg. a communications protocol, regular expression parser, LCD output) is done as a first step, and then the "main project" consists of assembling already-debugged parts
Both, they are not mutually exclusive. Except that I would put the .cpp and .h files into a separate folder and put that into the libraries folder (thus making a library). Then include the .h file in the main sketch.
You don't move the .cpp and .h file to the libraries folder until the library has been tested as part of a sketch folder, do you? It's easier, I think, to be able to switch tabs in the IDE rather than open a separate text editor, when developing/debugging a library.
True, there probably isn't much in it. I usually have some editor (Xcode happens to open on the Mac) for editing the library (has nice syntax colouring too) if my library has, er, bugs in it during development.
First of all it is great a pleasure for me to finally join in this illustrious community. I have found out about Platformio project on January of this year and ever since have been using it for many of my arduino projects. I use the Atom Text editor which I found to be extremely easy and intuitive to learn and use.
When I write codes in Arduino IDE, I can split the function bodies from the main ino files into discrete files following a sequential alphabetical naming scheme viz. A.main , B.pid, C.motor etc etc. When I hit the compile button, arduino compiles all these files and their associated header files without any error. Also the other ino files are capable of recognizing public variables, function calls written in libraries by other users installed into the Arduino IDE.
But in platformio, say I make the above files as such, main.cpp, pid.cpp, motor.cpp numerous errors are thrown including missing variable declarations from other libraries, for instance tft declaration of Adafruit GFX library is not recognized in other cpp files EXPECT in the main.cpp file.
Hence though I am not an expert in this subject matter, I strongly believe the platformio community/team should make ONE DEFINITIVE TUTORIAL to teach us less experienced programmers on how to create a multifile arduino project which will do the following
And a header-file (.h) with the function prototype and the struct definition. Arduino.h has to be included so you can use the variable type String. To clean up your project directory you can put the header-file in the include-folder while the source-file (.cpp) should be in the src-folder.
myhelperfunctions.h: