Your thoughts on programming practices for the Arduino

As I have said before, the Arduino is new to me. I've only been messing with it for about a month now. Prior to this, I've only ever done website based programming (html, javascript, php, etc).

So far, the somewhat complex (for me) sketch that I am working on works. But I have to question my methods as to if they are the best/proper way to do things. In this project, I have several sensors, motors, an LCD, clock and LEDs that need to be turned on/off/monitored/checked either continuously or at specific times. Oh hell, you get the point.

The way I have written it follows this format

//includes
//defines
//const ints
//other ints
//setup()
//loop(){
       //everything is checked/called by using functions
       //yes, everything
       //I have about 10+/- for now
}
//function 1
//function 2
//etc

As you can see, my method, although it works, is not the way most, if any at all, would program the Arduino. So, what advice would you give to a "noob" as far as the flow of programming an Arduino?

DangerToMyself:
As you can see, my method, although it works, is not the way most, if any at all, would program the Arduino. So, what advice would you give to a "noob" as far as the flow of programming an Arduino?

I don't see anything particularly wrong with your approach... well, I can't see anything wrong at all: lib including first, then defining stuff you need, global vars to follow, setup and loop method. I would say the usual general scheme is there. You already have coding experience, so I guess you know dividi et impera paradigm, and your function n let me think you're adopting it.
If the project you're working on is quite large, maybe you could consider to use dividi et impera paradigm with the project itself modularizing it (not just using a single .ino file).
Eventually, as a general rule, use char arrays instead of String objects (ref).

I'd separate the constants into Pin Numbers and Other Constants (Note: Constants are not always integers). If the pin numbers are declared in pin number order it is MUCH easier to tell if you have an accidental pin conflict. Put in comments for pins with special hardware. For example if your Arduino UNO sketch uses the SPI library you should add notes that pins 10, 11, 12, and 13 are generally conflicted. Similarly for the Wire (TWI/I2C) library uses A4 and A5.] and Serial uses pins 0 and 1.

You may (or may not) find some ideas in Planning and Implementing a Program

...R

It looks OK to me.
A lot of people will put all their code in loop() and setup() with no additional user-defined functions, but that's more of an "allowed simplification for beginners" than a "recommended style." I wish "we" were a lot more aggressive about suggesting that people use functions, but it quickly leads to relatively complex discussions about variable scope, argument passing, and pointers (due to C's lack of real string support.)

Don't forget to use local variables, not everything needs to be defined with a global scope. If a function needs to remember a variable across multiple calls but this variable is not used anywhere else, you could consider making that variable [

static

](https://www.arduino.cc/en/Reference/Static) to that function.

Thanks to everyone for the comments and pointers. I really do appreciate it. It's good to know that my approach, thus far, is not entirely a bad way to do things.

Robin2:
You may (or may not) find some ideas in Planning and Implementing a Program

...R

I will most certainly have a read through that. Thanks Robin2.

Goet:
If the project you're working on is quite large, maybe you could consider to use dividi et impera paradigm with the project itself modularizing it (not just using a single .ino file).
Eventually, as a general rule, use char arrays instead of String objects (ref).

Goet, you had me scratching my head there. I was like, "dividi et impera"? So, I Googled it. Yes, I have implemented a "divide and conquer" approach.

johnwasser:
I'd separate the constants into Pin Numbers and Other Constants (Note: Constants are not always integers). If the pin numbers are declared in pin number order it is MUCH easier to tell if you have an accidental pin conflict.

John, I have not used consecutive numbering or grouping them together. But that makes perfect sense. I will add that to my methods. I do try to add comments wherever things aren't blatantly obvious.

J-M-L:
Don't forget to use local variables, not everything needs to be defined with a global scope.

J-M-L, that right there has been one of the hardest things, for whatever reason, for me to get into my head. With other types of scripting, it seems the general rule is all variables must be called out at the beginning. I did some "cleaning" the other day. And this was one thing I looked at. Which variables didn't need to be called outside of a function. Really shortened my variable list at the top of my sketch.

Thanks again folks for taking the time to do what you do. There are some really good tips here.

DangerToMyself:
With other types of scripting, it seems the general rule is all variables must be called out at the beginning.

There aren't any other types of scripting because this is not script. If you look at other high level languages, local scope is quite common.

DangerToMyself:
J-M-L, that right there has been one of the hardest things, for whatever reason, for me to get into my head. With other types of scripting, it seems the general rule is all variables must be called out at the beginning. I did some "cleaning" the other day. And this was one thing I looked at. Which variables didn't need to be called outside of a function. Really shortened my variable list at the top of my sketch.

I blame the Arduino examples. They seem to use global variables for EVERYTHING. This help them avoid having to teach about 'scope', 'persistence', and 'initialization' since all global variables have global scope, all are persistent, and all are initialized to zero for you. They also don't generally use 'const', even where appropriate.

DangerToMyself:
that right there has been one of the hardest things, for whatever reason, for me to get into my head. With other types of scripting, it seems the general rule is all variables must be called out at the beginning. I did some "cleaning" the other day. And this was one thing I looked at. Which variables didn't need to be called outside of a function. Really shortened my variable list at the top of my sketch.

This can become a bit of a religious thing. Most of the time there is little practical difference whether you use global or local variables as long as you understand the difference. What often trips up newbies is accidentally creating local variables with the same name as global variables.

I like the list at the top of my program because when something is wrong I know where to look.

I reckon that the first requirement for an easy-to-develop program is the use of meaningful variable names. Whether one uses local or global variables is of secondary importance IMHO.

And, frankly, using local variables for cstrings is a complete PITA.
EDIT ... This is the idea I meant to convey
And, frankly, the business of passing cstrings into and out of functions is a complete PITA. It is much easier just to deal with them as global variables.

Of course I would put a very different value on the use of local variables if I were part of a team of programmers working on something with thousands of lines of code.

...R

And, frankly, using local variables for cstrings is a complete PITA.

why? allocating on the stack is not a bad practice if you need those just for a short moment

johnwasser:
I blame the Arduino examples. They seem to use global variables for EVERYTHING. This help them avoid having to teach about 'scope', 'persistence', and 'initialization' since all global variables have global scope, all are persistent, and all are initialized to zero for you. They also don't generally use 'const', even where appropriate.

Yes, however, some of them have had a recent makeover. There has been some improvement.

J-M-L:
why? allocating on the stack is not a bad practice if you need those just for a short moment

I see I expressed myself badly and you got in too quickly :slight_smile:

What I was intending to convey was the inconvenience of passing cstrings as parameters.

I will amend my earlier Reply.

...R

ok :slight_smile:

yes you need to consider lifespan of your variables

if somewhere else you remember just a pointer to a local (non static) variable, then you have a problem

I like to use C++ classes for components (loosely speaking). I like to use constructors for the pin numbers. And I like to give each component a setup() and loop() method. Each component is coded in such a way that it operates as a self-contained "thing".

I find that it makes development and testing simpler. Same in javascript, incidentally, even though having to use prototype is a pain.

I did up this web page on the topic with respect to using objects in arduino programming..

J-M-L:
ok :slight_smile:
yes you need to consider lifespan of your variables
if somewhere else you remember just a pointer to a local (non static) variable, then you have a problem

Without some clarification for newbies - this is a really good way to reduce RAM usage.

Globals, and statics - use memory forever, but local variables, and variables-within-functions - only use their particular RAM allocation for the duration they are 'in scope', and that little piece of memory may be dynamically re-deployed elsewhere when the program moves to other blocks of code.

Same applies for function calls. Once you get the skills, use the stack to pass params, and/or argc / argv[] to use RAM dynamically. It isn't important to blink a LED, or turn a steppper, but if you are shoe-horning a program into ever-shrinking memory - these tips can be useful!

Of course PROGMEM, and F() macros will also push some constant values out into FLASH as well (not 'variables')