[RESOLVED] Help creating/understanding custom library

I was having trouble understanding the making of libraries, and I was able to make one with the information provided by those who replied down below. If you just want the end result, just go to reply #18 that I made.

The original post is below:

Hi all,

I am currently trying to make a custom library, I have named it Tools. It is meant to contain some simple functions to help make my sketches easier to read. As of now, it has two functions: blink and flash. I kept it short to avoid confusion for now as I am not very good with libraries. I did the Arduino tutorial on libraries and that was ok but to use it, I needed an instance of the class at the top of the sketch, and I do not really want to have an instance of a class. I am trying to make it similar to something like 'pinMode' where I can pass arguments to the library function as the function is called.

What I did:

I used a simple sketch to try out the library below:

#include <Tools.h>

void setup() {
  blink(13, 500); //(Pin, Duration)
  flash(13, 500, 10); //(Pin, Duariton, Count)
}

void loop() {}

What I got:

The above code I used gave me these error messages

Arduino: 1.6.9 (Windows 10), Board: "Arduino/Genuino Uno"

In file included from C:\Users\*****\Desktop\Library_Test\Library_Test.ino:1:0:

C:\Users\*****\Documents\Arduino\libraries\Tools/Tools.h:16:1: error: 'Class' does not name a type

 Class Tools

 ^

C:\Users\*****\Desktop\Library_Test\Library_Test.ino: In function 'void setup()':

Library_Test:4: error: 'blink' was not declared in this scope

   blink(13, 500); //(Pin, Duration)

                ^

Library_Test:5: error: 'flash' was not declared in this scope

   flash(13, 500, 10); //(Pin, Duariton, Count)

                    ^

exit status 1
'blink' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

What I have:

Tools.h

/*
  First library, a simple collection of tools, but for the sake of simplicity,
  there are only a few functions as of now

  Created July 4, 2016

*/



#ifndef Tools_h
#define Tools_h

#include "Arduino.h"

Class Tools
{
  public:
    void blink(byte pin, int duration);
    void flash(byte pin, int duration, int counts);
  private:
    byte _pin;
    byte _duration;
    byte _counts;
}

#endif

Tools.cpp

#include "Arduino.h"
#include "Tools.h"

void Tools::blink(byte pin, int duration)
{
  pinMode(pin, OUTPUT);

  digitalWrite(pin, HIGH);
  delay(duration / 2.0);
  digitalWrite(pin, LOW);
  delay(duration / 2.0);
}

void Tools::flash(byte pin, int duration, int counts)
{
  pinMode(pin, OUTPUT);

  for (int x = 0; x < counts; x++)
  {
    digitalWrite(pin, HIGH);
    delay(duration / 2.0);
    digitalWrite(pin, LOW);
    delay(duration / 2.0);
  }
}

Any help is appreciated.

class Tools
{

Then simply don't create a class...

And in my opinion a name like Tools, blink, and flash are a bit generic. Call them something unique like MikeTools, mikeFlash() and mikeBlink() so you know they are from the library.

Also some comment about the library:

Why do you use a float inside delay()? Delay can't handle floats.

Why do you use delay()? Delay() is blocking code and if you want to do anything else then blinking a led you should avoid it. Have a look at Blink without delay.

And last, the whole thing about functions and libraries is so you can reuse code. And flashing is only a copy of blink for a number of time. So why isn't flash() using blink()?

void myFlash(byte pin, unsigned int duration, unsigned int counts){
  for(unsigned int i = 0; i < counts, i++){
    blink(pin, duration);
  }
}

In addition to AWOL's post, you must declare an instance of that class, then use it with the public functions.

#include <Tools.h>
Tools myTools;

void setup() {
  myTools.blink(13, 500); //(Pin, Duration)
  myTools.flash(13, 500, 10); //(Pin, Duariton, Count)
}

void loop() {}

Or simply don't create a class... A class without variables, only methods is a bit useless.

I took everything into account, I'm not planning on worrying about a delay() yet as its not very high priority and I would rather get it working as is for now.

The new files:

MikeTools.h

/*
  First library, a simple collection of tools, but for the sake of simplicity,
  there are only a few functions as of now

  Created July 4, 2016

*/



#ifndef MikeTools_h
#define MikeTools_h

#include "Arduino.h"

class MikeTools
{
  public:
    void mikeBlink(byte pin, int duration);
    void mikeFlash(byte pin, int duration, int counts);
  private:
}

#endif

MikeTools.cpp:

#include "Arduino.h"
#include "MikeTools.h"

void MikeTools::mikeBlink(byte pin, int duration)
{
  pinMode(pin, OUTPUT);

  digitalWrite(pin, HIGH);
  delay(duration / 2);
  digitalWrite(pin, LOW);
  delay(duration / 2);
}

void MikeTools::mikeFlash(byte pin, int duration, int counts)
{
  pinMode(pin, OUTPUT);

  for (int x = 0; x < counts; x++)
  {
    digitalWrite(pin, HIGH);
    delay(duration / 2);
    digitalWrite(pin, LOW);
    delay(duration / 2);
  }
}

I ran the following code:

#include <MikeTools.h>
MikeTools sketchTools;

void setup() {
  // put your setup code here, to run once:
  sketchTools.mikeBlink(13, 1000);
  sketchTools.mikeFlash(13, 1000, 10);
}

void loop() {}

I got this as the error message:

Arduino: 1.6.9 (Windows 10), Board: "Arduino/Genuino Uno"

sketch_jul07a:2: error: expected initializer before 'sketchTools'

 MikeTools sketchTools;

           ^

C:\Users\\Desktop\sketch_jul07a\sketch_jul07a.ino: In function 'void setup()':

sketch_jul07a:6: error: 'sketchTools' was not declared in this scope

   sketchTools.mikeBlink(13, 1000);

   ^

exit status 1
expected initializer before 'sketchTools'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I haven't tried it, but this looks bad. No semicolon after the class name.

class MikeTools;
{

I took that out in the version that I compiled and got the same thing

Mike44449:
I took everything into account,

No you did not... You're still making a class...

And still not reusing code...

Try

/*
  First library, a simple collection of tools, but for the sake of simplicity,
  there are only a few functions as of now

  Created July 4, 2016

*/



#ifndef MikeTools_h
#define MikeTools_h

#include "Arduino.h"

  void mikeBlink(byte pin, int duration);
  void mikeFlash(byte pin, int duration, int counts);

#endif
#include "Arduino.h"
#include "MikeTools.h"

void mikeBlink(byte pin, unsigned int duration)
{
  pinMode(pin, OUTPUT);

  digitalWrite(pin, HIGH);
  delay(duration / 2);
  digitalWrite(pin, LOW);
  delay(duration / 2);
}

void mikeFlash(byte pin, unsigned int duration, unsigned int counts)
{
  for (unsigned int x = 0; x < counts; x++)
  {
    mikeBlink(pin, duration);
  }
}

Mike44449:
I'm not planning on worrying about a delay() yet as its not very high priority

So basically you don't plan to do anything else then blinking leds in sequence? So buttons as input? No multiple blinking leds?

No, not at the moment, It is ok that the LEDs blinking will stop the code, I plan on looking into blink without delay but for now, I dont want to jump in with all the details until the library at least compiles

septillion:
Or simply don't create a class... A class without variables, only methods is a bit useless.

Not at all. The requirement for member functions or even an instance is simply a product of a fundamental misunderstanding of what a a class/interface can achieve.

A bit off topic, yes, but still a class has more uses than you give it merit.

Alright alright, you can go full out C++ and make them static functions etc. But a lot of Arduino code is already C so why not simple put the functions into a library.

@Mike
library != class

This compiles ok.

Sketch

#include <MikeTools.h>

MikeTools sketchTools;

void setup() {
  // put your setup code here, to run once:
  sketchTools.mikeBlink(13, 1000);
  sketchTools.mikeFlash(13, 1000, 10);
}

void loop() {}

MikeTools.h

#ifndef MikeTools_h
#define MikeTools_h

class MikeTools {
  public:
    void mikeBlink(byte pin, int duration);
    void mikeFlash(byte pin, int duration, int counts);
};

#endif

MikeTools.cpp

#include "Arduino.h"
#include "MikeTools.h"

void MikeTools::mikeBlink(byte pin, int duration)
{
  pinMode(pin, OUTPUT);

  digitalWrite(pin, HIGH);
  delay(duration / 2);
  digitalWrite(pin, LOW);
  delay(duration / 2);
}

void MikeTools::mikeFlash(byte pin, int duration, int counts)
{
  pinMode(pin, OUTPUT);

  for (int x = 0; x < counts; x++)
  {
    digitalWrite(pin, HIGH);
    delay(duration / 2);
    digitalWrite(pin, LOW);
    delay(duration / 2);
  }
}

SurferTim:
This compiles ok.

Good for you! But why do you keep ignoring comments and only use comments you appear to like?

@septillio: Because he is trying to learn how to build a custom library. You are ignoring that fact. He may want to add other variables and functions later. Have you considered that?

Yes I have. But all functions have no relation to a class what so ever... Like I said, library != class. So making a library has nothing to do with classes. So to have a set of tools / common functions, fine, but don't use a class. If you want to do more interesting stuff, like making a library to blink multiple leds without blink, then start making / learning how to make a class. One aspect to learn when making a library is to learn when to use a class or not (or full C++, when to make things static methods or not).

And I was not only talking about the class thing. The "whole idea of functions is you can reuse them" is also ignored. flash() is still 90% a copy of the code from blink()....

@septillion The whole reason i'm even doing this is to A). Improve readability and B) Learn a new skill (library making). I have a few sketches that almost exceed 1000 lines, not counting empty lines and I'm sure you can tell I'm not the most advanced arduino user and yes, a function that I can put into each sketch would do the same thing int terms of increasing readability but why not learn a new thing and just make a library?

I am simply getting help to make a library with two functions, and in doing so I learned how to add functions as I see fit. No I probably do not need a class, so I didn't use one.

@SurferTim Thanks for the code, I plan on first, taking the delay out and then adding the rest of the functions.

Mike44449:
and just make a library?

Simply because making a library has NOTING to do with classes. Yes, a lot of libraries use classes but you don't need to. You can also just add functions to a seperate file, put that in the library folder and include that. That's STILL a library! It's a common misconception under newbies...

Mike44449:
No I probably do not need a class, so I didn't use one.

Yes you did... Right here:

class MikeTools {
  public:

Mike44449:
I have a few sketches that almost exceed 1000 lines,

If you never reuse code (like blink() inside flash()) then yeah, the number of lines if growing fast...

I'm sorry, you are not aware of the files and code I ended up using. I forgot to update the first post.
I took the information from you and SurferTim and created the library. And yes, there is a class in this one.

The current Utilities.h:

#ifndef Utilities_h
#define Utilities_h

class Utilities {
  public:
    void uBlink(byte pin, int duration);
    void uFlash(byte pin, int duration, int counts);
    void rawPwm(byte pin, int input);
};

#endif

The current Utilities.cpp:

#include "Arduino.h"
#include "Utilities.h"

void Utilities::uBlink(byte pin, int duration)
{
  pinMode(pin, OUTPUT);

  digitalWrite(pin, HIGH);
  delay(duration / 2);
  digitalWrite(pin, LOW);
  delay(duration / 2);
}

void Utilities::uFlash(byte pin, int duration, int counts)
{
  pinMode(pin, OUTPUT);

  for (int x = 0; x < counts; x++)
  {
    digitalWrite(pin, HIGH);
    delay(duration / 2);
    digitalWrite(pin, LOW);
    delay(duration / 2);
  }
}

void Utilities::rawPwm(byte pin, int input)
{
  int value = map(input, 0, 1023, 0, 255);
  pinMode(pin, OUTPUT);
  analogWrite(pin, value);
}

The sketch to use it:

#include <Utilities.h>
Utilities sketchTools;

void setup() {
  // put your setup code here, to run once:
  sketchTools.uBlink(13, 1000);
}

void loop() {
  // put your main code here, to run repeatedly:
  sketchTools.rawPwm(5, analogRead(A0));
  sketchTools.uFlash(13, 500, 4);
}

For crying out loud, why is flash() still a copy past of blink()! :cry: :cry: :cry:

But alright, you want to make classes? Make the functions static. Non of the functions rely on states of of the object. So why bother making an object.

Also, now the important name is very general and the unimportant names are specific. It doesn't matter how you call anything inside a class, that's up to you. But Utilities as a class name is very very general... There is a change of it colliding with another class in the future. That's my I opted for the "Mike" prefix.

But have a look at:

#ifndef MyUtil_h
#define MyUtil_h

#include "Arduino.h" //don't forget to include arduino.h

class MyUtil {
  public:
    static void blink(byte pin, unsigned int duration);
    static void flash(byte pin, unsigned int duration, unsigned int counts);
    static void rawPwm(byte pin, int input);
  private:
    MyUtil() {};
};

#endif
#include "Arduino.h"
#include "MyUtil.h"

//made duration unsigned because you don't want a negative number
void MyUtil::blink(byte pin, unsigned int duration)
{
  pinMode(pin, OUTPUT);

  digitalWrite(pin, HIGH);
  delay(duration / 2);
  digitalWrite(pin, LOW);
  delay(duration / 2);
}

//made duration and counts unsigned because you don't want a negative number
void MyUtil::flash(byte pin, unsigned int duration, unsigned int counts)
{
  for (unsigned int x = 0; x < counts; x++)
  {
    MyUtil::blink(pin, duration);
  }
}

void MyUtil::rawPwm(byte pin, int input)
{
  //int value = map(input, 0, 1023, 0, 255);
  //analogWrite alreay calls pinMode
  //pinMode(pin, OUTPUT);
  analogWrite(pin, map(input, 0, 1023, 0, 255));
}

And just use it directly like

MyUtil::flash(13, 1000, 10);

No need to create an object. I even made that impossible...