Using #includes

I use a standard set of Keypad and LCD includes in my sketches. To save time I use the following sketch with an include “mystuff.h” My question is programming this way to keep things easy to understand while it does work perfectly. Is this considered bad coding? Or bad use of a header file? Should I make it a Library?

I use a thin film 4 X 4 keypad and a 2004A I2C display on most of my Sketches Below is an example of how I use it.

Any suggestions , comments or corrections would be appreciated.

Save as mySetup.ino

/*
   Arduino Keypad Program
*/
#include "mySetup.h"

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor((halfCols - (msglen  / 2)), 0);
  lcd.print(msg1);
  lcd.setCursor((halfCols - (msglen2 / 2)), 1);  
  lcd.print(msg2);   
  lcd.setCursor((halfCols - (msglen3 / 2)), 2);
  lcd.print(msg3);
  delay(3000); //Wait for display to show info
  clr(1); //Then clean it
  delay (2000);
  clr(2);
  delay(2000);
}

void loop() {
  key = kpd.getKey(); //storing pressed key value in a char

  if (key != NO_KEY)
    DetectKeys();

  if (result == true)
    CalculateResult();

  DisplayResult();
}


void CalculateResult()
{
  if (action == '+')
    Number = Num1 + Num2;

  if (action == '-')
    Number = Num1 - Num2;

  if (action == '*')
    Number = Num1 * Num2;

  if (action == '/')
    Number = Num1 / Num2;
}

void DisplayResult()
{
  lcd.setCursor(0, 0);   // set the cursor to column 0, line 1
  lcd.print(Num1); lcd.print(action); lcd.print(Num2);

  if (result == true)
  {
    lcd.print(" =");  //Display the result
    lcd.print(Number);
  }

  lcd.setCursor(0, 1);   // set the cursor to column 0, line 1
  lcd.print(Number); //Display the result
}

Save this as mySetup.h

//---------------------------Includes & definitions-------------------------------------//
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#define LCD_COLS 16									// Total Columns of the LCD_ROWS
#define LCD_ROWS 2								// Total Rows of the LCD
#define halfCols (LCD_COLS/2)						// Center of the Columns. Used for centering Text on the screen
#define msg1 ("Line 1")						// Default Text for Line 1 
#define msg2 ("Line 2")								// Default Text for Line 2
#define msg3 ("Line 3 of 4")						// Default Text for Line 3
LiquidCrystal_I2C lcd(0x27,LCD_COLS,LCD_ROWS);		// My default LCD_I2C 
void(* resetFunc) (void) = 0; 						//declare reset function @ address 0void(* resetFunc) (void =0);

int x;
int msglen = sizeof(msg1);							// Length in Characters of msg1
int msglen2= sizeof(msg2);							// Length in Characters of msg2
int msglen3= sizeof(msg3);							// Length in Characters of msg3
char key,action;									// Initialize Characters
long Num1, Num2, Number;							// Initialize long variables
boolean result = false;

//-------------------Keypad Setup-------------------------//

const byte ROWS = 4;								// Rows and Columns of LCD
const byte COLS = 4;

char keys[ROWS][COLS] =								// Keypad character array
{ {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6}; 					//connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; 					//connect to the column pinouts of the keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); //  Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

//-------------------------------------------------------//

bool a = true;


													// A simple but effective way to clear a line of text. 
													// Just type clr(1) to clear the first line 
													// clr(2) for the second line etc...

void clr(int x) {									// Clear line Function
  lcd.setCursor(0,x-1);								// Set the Line number to x where x is 
  lcd.print("                   ");
}

void DetectKeys()
{
  lcd.clear(); //Then clean it
  if (key == '*') //If cancel Button is pressed
  {
    Serial.println ("Button Cancel");
    Number = Num1 = Num2 = 0;
    result = false;
  }

  if (key == '1') //If Button 1 is pressed
  { Serial.println ("Button 1");
    if (Number == 0)
      Number = 1;
    else
      Number = (Number * 10) + 1; //Pressed twice
  }

  if (key == '4') //If Button 4 is pressed
  { Serial.println ("Button 4");
    if (Number == 0)
      Number = 4;
    else
      Number = (Number * 10) + 4; //Pressed twice
  }

  if (key == '7') //If Button 7 is pressed
  { Serial.println ("Button 7");
    if (Number == 0)
      Number = 7;
    else
      Number = (Number * 10) + 7; //Pressed twice
  }


  if (key == '0')
  { Serial.println ("Button 0"); //Button 0 is Pressed
    if (Number == 0)
      Number = 0;
    else
      Number = (Number * 10) + 0; //Pressed twice
  }

  if (key == '2') //Button 2 is Pressed
  { Serial.println ("Button 2");
    if (Number == 0)
      Number = 2;
    else
      Number = (Number * 10) + 2; //Pressed twice
  }

  if (key == '5')
  { Serial.println ("Button 5");
    if (Number == 0)
      Number = 5;
    else
      Number = (Number * 10) + 5; //Pressed twice
  }

  if (key == '8')
  { Serial.println ("Button 8");
    if (Number == 0)
      Number = 8;
    else
      Number = (Number * 10) + 8; //Pressed twice
  }


  if (key == '#')
  { Serial.println ("Button Equal");
    Num2 = Number;
    result = true;
  }

  if (key == '3')
  { Serial.println ("Button 3");
    if (Number == 0)
      Number = 3;
    else
      Number = (Number * 10) + 3; //Pressed twice
  }

  if (key == '6')
  { Serial.println ("Button 6");
    if (Number == 0)
      Number = 6;
    else
      Number = (Number * 10) + 6; //Pressed twice
  }

  if (key == '9')
  { Serial.println ("Button 9");
    if (Number == 0)
      Number = 9;
    else
      Number = (Number * 10) + 9; //Pressed twice
  }

  if (key == 'A' || key == 'B' || key == 'C' || key == 'D') //Detecting Buttons on Column 4
  {
    Num1 = Number;
    Number = 0;
    if (key == 'A')
    {
      Serial.println ("Addition");
      action = '+';
    }
    if (key == 'B')
    {
      Serial.println ("Subtraction");
      action = '-';
    }
    if (key == 'C')
    {
      resetFunc();
      action = 'Reset';
    }
    if (key == 'D')
    {
      Serial.println ("Division");
      action = '/';
    }

    delay(100);
  }

}
#define msg1 ("Line 1")                     // Default Text for Line 1 
#define msg2 ("Line 2")                             // Default Text for Line 2
#define msg3 ("Line 3 of 4")                        // Default Text for Line 3

https://www.google.com/search?q=arduino+f+macro

Is this considered bad coding?

Yes. A header file should only define things. It should not implement any functionality.

You should rename that file to a .ino file and copy it into each sketch folder. The IDE will sew the files in that folder together at compile time, in alphabetical order.

ZilliQuister:
Is this considered bad coding?

If you ever transition to a multi-file project then what you’ve done will be a problem.

ZilliQuister:
Should I make it a Library?

Looks like a great candidate for a library.

PaulS: Yes. A header file should only define things. It should not implement any functionality.

You should rename that file to a .ino file and copy it into each sketch folder. The IDE will sew the files in that folder together at compile time, in alphabetical order.

So if I renamed mySetup.h to mySetup2.ino the original mySetup.ino would just automatically add the code there so I could use it? Would it not give me errors at compile time because some of the functions required by mySetup.ino are in mySetup2.ino? I'll have to try that. Also I understand that my messages should be in the main Sketch file. I just did it that way for this particular sketch to test if the header file would work that way.

By breaking this down into 3 separate files with mySetup.h containing only my definitions and includes. Then convert my functions to a library and add the mySetup.h to that library.( mySetup.cpp ). and lastly the actual Sketch. Is that correct?

Thanks again for you assistance in this matter.

[quote author=Coding Badly date=1559843080 link=msg=4201206]

#define msg1 ("Line 1") // Default Text for Line 1 
#define msg2 ("Line 2") // Default Text for Line 2
#define msg3 ("Line 3 of 4") // Default Text for Line 3

https://www.google.com/search?q=arduino+f+macro

[/quote]

These definitions listed above were to see if a header file would include them in a short sketch and be usable. I will be placing these in an external 24LC64 EEProm and read in from memory block added by defining their address in the header file. I think that will be the best way to do this for my main project. Thanks for the link I'll play around with that and see if it makes sense to use it in other sketches.

I'll Most likely have definitions that will give the default [NAME] [ROTATION] [SPEED] [STEP] [COMPANY NAME] [ DIRECTIONS ] etc that way they will not be using main memory.

Along those lines, and for what it’s worth, here’s my recommendation (in Reply #3): https://forum.arduino.cc/index.php?topic=588837.msg4005111#msg4005111

ZilliQuister: Should I make it a Library?

The primary benefit of libraries is they allow you to share the same code between multiple projects.

Another benefit is they allow you to hide complex implementation code from beginners who might be intimidated by it. The beginner can just learn the API of the library and not worry about the inner details of the library. When the time comes that they become curious about this, they can always just open up the library files and have a look.

ZilliQuister: So if I renamed mySetup.h to mySetup2.ino the original mySetup.ino would just automatically add the code there so I could use it?

I don't understand what you mean by "automatically add the code there".

ZilliQuister: Would it not give me errors at compile time because some of the functions required by mySetup.ino are in mySetup2.ino?

When you compile code in the Arduino IDE/arduino-cli/Arduino Web Editor, the .ino files of your sketch go through a preprocessing step to convert them into valid C++ code. During sketch preprocessing, if your sketch has multiple .ino files, they are concatenated into a single file starting with the .ino file that matches the folder name, followed by the rest of the .ino files in alphabetical order. So there is no functional difference between a single .ino file vs several. The benefit to having multiple .ino files is that it makes it easy to quickly navigate through a large program by clicking on the tab you want instead of scrolling through thousands of lines of code every time.

Hey, Thanks for all the programming etiquette. I see I still have a lot to learn. I will take yours and everyone else's comments and suggestion and work with those . Hopefully that will make my code a bit more legible and easier to understand for the beginners like myself.

What I've learned:

1) Header files should only contain definitions and not functions.

2) If I use a lot of definitions I should consider using macro f() function. in my lcd.print and Serial.print statements.

3) I should break down my code to smaller easier to manage sketches.

4) You can use multiple *ino files that concatenate at compile time.