A Lot of Confusion in Writing My First Library

Hey guys!
I'm having two issues with making my own library.

  1. I can't seem to understand how to actually make my own library. I've poured through Google, YouTube and these forums on the subject, but I'm still having a hard time with it. I understand the concept but actually writing it is throwing me for a loop.

  2. Once I actually make a custom library, how can I pass results of a specific function variable in or out of that created library? Would I simply make the variable that I need as a global variable inside the sketch I'm using it in?

Reaching out in hopes someone can guide me to a better resource than what I've been finding!

IDE v. 1.8.5
(The Sketch I Want to Turn Into A Custom Library)

//----------LIBRARIES----------//
#include <SoftwareSerial.h>

//----------GLOBAL VARIABLES----------//
SoftwareSerial gprsSerial(7, 8);


//-------------------------//
//----------SETUP----------//
//-------------------------//
void setup()
{
  gprsSerial.begin(9600); //GPRS shield baud rate
  Serial.begin(9600); //Starts the serial monitor at 9600 bauds
}


//------------------------//
//----------LOOP----------//
//------------------------//
void loop()
{
  if (Serial.available()) //If there is incoming serial data
    switch (Serial.read()) //Read the character
    {
      case '1': //If the character is '1'
        TempTooHighTextMessage(); //Sends the text message for when the growing chamber is too hot >=85F
        break;
      case '2': //If the character is '2'
        TempTooHighClearedTextMessage(); //Sends the text message for when the high temperature in the growing chamber is okay <=77F
        break;
      case '3': //If the character is '3'
        TempTooLowTextMessage(); //Sends the text message for when the growing chamber is too cold <=70
        break;
      case '4': //If the character is '4'
        TempTooLowClearedTextMessage(); //Sends the text message for when the low temperature in the growing chamber is okay >=76
        break;
      case '5': //If the character is '5'
        HumidTooHighTextMessage(); //Sends the text message for when the humidity in the growing chamber is too high >=75%
        break;
      case '6': //If the character is '6'
        HumidTooHighClearedTextMessage(); //Sends the text message for when the humidity in the growing chamber is okay <=65%
        break;
    }
  if (gprsSerial.available()) //If the shield has something to say
  {
    Serial.write(gprsSerial.read()); //Display the output of the shield
  }
}

//----------FUNCTIONS----------//
void TempTooHighTextMessage()
{
  Serial.println("Sending Text...");
  gprsSerial.print("AT+CMGF=1\r"); //Set the shield to SMS mode
  gprsSerial.println("AT+CMGS = \"+XXXXXXXXXXX\""); //Phone number taken out because I'm posting it online. 
  gprsSerial.println("Temperature is too high in the growing chamber (85F). System is automatically lowering the temperature now"); //The content of the text
  gprsSerial.print((char)26);//The ASCII code of the ctrl+z is 26 (required according to the datasheet)
  gprsSerial.println();
  Serial.println("Text Sent.");
}

void TempTooHighClearedTextMessage()
{
  Serial.println("Sending Text...");
  gprsSerial.print("AT+CMGF=1\r"); //Set the shield to SMS mode
  gprsSerial.println("AT+CMGS = \"+XXXXXXXXXXX\""); //Phone number taken out because I'm posting it online.
  gprsSerial.println("Temperature in the growing chamber has been cooled down successfully (77F)"); //The content of the text
  gprsSerial.print((char)26);//The ASCII code of the ctrl+z is 26 (required according to the datasheet)
  gprsSerial.println();
  Serial.println("Text Sent.");
}

void TempTooLowTextMessage()
{
  Serial.println("Sending Text...");
  gprsSerial.print("AT+CMGF=1\r"); //Set the shield to SMS mode
  gprsSerial.println("AT+CMGS = \"+XXXXXXXXXXX\""); //Phone number taken out because I'm posting it online.
  gprsSerial.println("Temperature is too low in the growing chamber (70F). System is automatically raising the temperature now"); //The content of the text
  gprsSerial.print((char)26);//The ASCII code of the ctrl+z is 26 (required according to the datasheet)
  gprsSerial.println();
  Serial.println("Text Sent.");
}

void TempTooLowClearedTextMessage()
{
  Serial.println("Sending Text...");
  gprsSerial.print("AT+CMGF=1\r"); //Set the shield to SMS mode
  gprsSerial.println("AT+CMGS = \"+XXXXXXXXXXX\""); //Phone number taken out because I'm posting it online.
  gprsSerial.println("Temperature in the growing chamber has been raised successfully (76F)"); //The content of the text
  gprsSerial.print((char)26);//The ASCII code of the ctrl+z is 26 (required according to the datasheet)
  gprsSerial.println();
  Serial.println("Text Sent.");
}

void HumidTooHighTextMessage()
{
  Serial.println("Sending Text...");
  gprsSerial.print("AT+CMGF=1\r"); //Set the shield to SMS mode
  gprsSerial.println("AT+CMGS = \"+XXXXXXXXXXX\""); //Phone number taken out because I'm posting it online.
  gprsSerial.println("Humidity is too high in the growing chamber (75%). System is automatically lowering the humidity now"); //The content of the text
  gprsSerial.print((char)26);//The ASCII code of the ctrl+z is 26 (required according to the datasheet)
  gprsSerial.println();
  Serial.println("Text Sent.");
}

void HumidTooHighClearedTextMessage()
{
  Serial.println("Sending Text...");
  gprsSerial.print("AT+CMGF=1\r"); //Set the shield to SMS mode
  gprsSerial.println("AT+CMGS = \"+XXXXXXXXXXX\""); //Phone number taken out because I'm posting it online.
  gprsSerial.println("Humidity in the growing chamber has been lowered successfully (65%)"); //The content of the text
  gprsSerial.print((char)26);//The ASCII code of the ctrl+z is 26 (required according to the datasheet)
  gprsSerial.println();
  Serial.println("Text Sent.");
}

(The sketch that I want to use the custom library in)

//----------LIBRARIES----------//
#include <TimeLib.h> //Used by the alarm system. Might have to delete this as a duplicate?
#include <TimeAlarms.h> //Used by the alarm system. Might have to delete this as a duplicate?
#include <DHT.h>

//----------CONSTANTS----------//
#define DHTPIN 2 //Data pin from the sensor connects to Arduino pin# 2.
#define DHTTYPE DHT11 //DHT 11 (AM2302)
DHT dht(DHTPIN, DHTTYPE); //Initializes the DHT sensor for normal 16mhz Arduinos.

//----------GLOBAL VARIABLES----------//
int temperature = 0; //Used by the temperature sensor. Real-time temperature data (F).

int chk;
float hum; //Stores humidity value.
float temp; //Stores temperature value.

const int InlineFan = 13; //Names Arduino pin# 13 Inline Fan.
const int PcFans = 12; //Names Arduino pin# 13 Inline Fan.
const int HeatingElement = 11; //Names Arduino pin# 13 Inline Fan.

//-------------------------//
//----------SETUP----------//
//-------------------------//
void setup()
{
  Serial.begin(9600);
  dht.begin();
  setTime(8, 29, 58, 1, 1, 11); //Used by the alarm system. Sets the time to Saturday 8:29:00am Jan 1 2011
  pinMode(13, OUTPUT); //Sets Arduino pin# 13 as an output.
  pinMode(12, OUTPUT); //Sets Arduino pin# 12 as an output.
  pinMode(11, OUTPUT); //Sets Arduino pin# 11 as an output.
  digitalWrite(13, LOW);
  digitalWrite(12, LOW);
  digitalWrite(11, LOW);
}



//------------------------//
//----------LOOP----------//
//------------------------//
void loop()
{
  digitalClockDisplay(); //Used by the alarm system. Displays the clock printout in the serial monitor.
  TemperatureControl(); //Calls the TemperatureControl function.
}

//----------FUNCTIONS----------//
void TemperatureControl()
{
  hum = dht.readHumidity(); //Read data and store it to variable hum
  temp = dht.readTemperature(true); //Read data and store it to variable temp
  Serial.print("Humidity: ");
  Serial.print(hum);
  Serial.print("%, Temperature: ");
  Serial.print(temp);
  Serial.println("(F)");
  delay(1000); //Delay 1 sec.
  HighTemperature(); //Calls the HighTemperature function.
  LowTemperature(); //Calls the LowTemperature function.
  HighHumidity(); //Calls the HighHumidity function.
}

void HighTemperature()
{
  if (temp >= 85) //If the temperature in the growing chamber rises above 85(F):
  {
    Serial.write(1);
    digitalWrite(InlineFan, HIGH); //Turn ON the relay for the Inline Fan.
    digitalWrite(PcFans, HIGH); //Turn ON the relay for the PC fans.
    TempTooHighTextMessage();
  }
  else if (temp <= 77) //Once the temperature in the growing chamber drops to 77(F) or below:
  {
    Serial.write(2);
    digitalWrite(InlineFan, LOW); //Turns OFF the relay for the Inline Fan.
    digitalWrite(PcFans, LOW); //Turns OFF the relay for the PC fans.
    TempTooHighClearedTextMessage();
  }
}

void LowTemperature()
{
  if (temp <= 70) //If the tempature in the growing chamber drops below 70(F):
  {
    Serial.write(3);
    digitalWrite(HeatingElement, HIGH); //Turn ON the relay for the Heating Element.
    TempTooLowTextMessage();
  }
  else if (temp >= 76) //Once the growing chamber temperature rises back up to 76(F) or greater:
  {
    Serial.write(4);
    digitalWrite(HeatingElement, LOW); //Turn OFF the relay for the Heating Element.
    TempTooLowClearedTextMessage();
  }
}

void HighHumidity()
{
  if (hum >= 75) //If the humidity in the growing chamber rises above 70%:
  {
    Serial.write(5);
    digitalWrite(InlineFan, HIGH); //Turn ON the relay for the Inline Fan.
    digitalWrite(PcFans, HIGH);  //Turn ON the relay for the PC fans.
    HumidTooHighTextMessage();
  }
  else if (hum <= 65) //Once the humidity in the growing chamber drops to 65% or below:
  {
    Serial.write(6);
    digitalWrite(InlineFan, LOW); //Turns OFF the relay for the Inline Fan.
    digitalWrite(PcFans, LOW); //Turns OFF the relay for the PC fans.
    HumidTooHighClearedTextMessage();
  }
}

void digitalClockDisplay()
{
  //Digital clock display of the time.
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}

void printDigits(int digits)
{
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

I understand the concept but actually writing it is throwing me for a loop.

First decide what the library should do. I know that you have some code that you wish to turn into a library but which functions do you want to put into the library ?

Many Arduino libraries are written as classes which allows you to create multiple objects of the same kind with each instance being separate. An example of this would be the Servo library, which you may have used.

However, libraries do not need to involve classes if all you want to do is to have a bunch of utility functions that you can call into your programs using the #include command.

A library typically consists of two files with the same name but different extensions. The .h file contains function prototypes and variable declarations and the corresponding .cpp file contains the actual functions.

At its simplest it could be something like this

Main sketch

#include "someFunctions.h"

void setup()
{
  Serial.begin(115200);
  printMessage("Hello");
  printMessage("World");  
}

void loop()
{
}

someFunctions.h

#include <Arduino.h>
void printMessage(char *);

someFunctions.cpp

#include "someFunctions.h"
void printMessage(char * theMessage)
{
  Serial.println(theMessage);
}

Put all three in the same folder which is easiest done by adding tabs to the IDE and giving them appropriate names which will create the files

To get read access to a variable,write a function/method that returns the variable; look at e.g. Serial.read().

If you want to set a variable, write a function/method that takes a parameter and assign it to the variable; look e.g.at Serial.begin().

@ard_nubie
I've already read that page you linked, however, I'll re-read it since you've found it useful and hopefully pick up a few more concepts that I may have missed. Thank you.

@UKHeliBob
Thank you very much for the leads and samples. I'm looking into how to use classes, instances, and #include now! :slight_smile:

@sterretje
Thank you for the response. I understand what you're saying about the Serial.read() and Serial.write(). Makes sense.
Follow-up question; if I unplug my Arduino from my IDE and run off a battery, will I still be able to pass my functions data via the Serial commands?

@Robin2
Oh... I had no idea that what you had suggested was actually possible. Doing it your way might change everything seeing as the code was made just for my project. I'll look into that now :slight_smile:

If you are writing the code just for your own use (i.e. not for general publication) then there may be no need to put the code into a library. It may be sufficient to put it in a .ino file or a .h file that you include in your program. That way you avoid the complexities of complying with the library system.

Of course if the purpose of the exercise is just to lean how to create a library, then please ignore my comment.

...R

PS. If you are planning to publish your library please write some very clear documentation to go along with it.