Making my own class

I found a tutorial here on Arduino forum of how to write my own class, as well as on Adafruit.

The problem is that they have different syntax! So which one is correct?

public:
  Flasher(int pin, long on, long off)

vs

Flasher::Flasher(int pin, long on, long off)

And also how can I compile my class to see if everything is correct? And when I finish my class, where can I publish so other ones can use it?

The problem is that they have different syntax!

For the header and source files, of course they do. The header file defines the constructor (the method with the same name as the class); the source file implements the method, using the scope resolution operator.

And also how can I compile my class to see if everything is correct?

Include the header file in a sketch.

PaulS: For the header and source files, of course they do. The header file defines the constructor (the method with the same name as the class); the source file implements the method, using the scope resolution operator. Include the header file in a sketch.

Both were in the source file....

So which tutorial to use?

And should class name only have capital letters?

Both were in the source file....

The 2nd snippet you posted appears to come from the Adafruit site, which I'm sorry to say is NOT the source of good examples.

The 1st snippet is nowhere to be found on the Adafruit site.

The problem, from my perspective, with the Adafruit site is that it suggests that the class definition and the class implementation should be in the same file. I strongly disagree with that. There are good reasons for isolating the implementation from the definition, and no reasons (other than laziness) for not isolating them.

In the definition, the constructor would be declared as in your first snippet. In the implementation, the function being implemented would be defined as in your second snippet.

So which tutorial to use?

The Arduino site does isolate the definition of the class (in the header file) from the implementation of the class (in the source file). So, that is the one to follow, IMHO.

And should class name only have capital letters?

By convention, all capital letter names are reserved for constants. Since a class is not a constant, no. Class names usually start with a capital letter, though, and use pascal-case (each word in the name starts with a capital letter. That is like camel-case, where each word, except the first, starts with a capital letter).

I recently tackled this myself starting with that same article on adafruit.

Those 2 links show different things, the adafruit link shows how to make a very simplified class, and the arduino link shows how to make a library.

A class can be part of the source file, A library is a class that has been separated into separate .h and .cpp files.

Here is the link to the thread where @BulldogLowell showed me how to get from the simplified class shown on the adafruit site to a proper class. Help debugging my button class

Then you can use the Arduino link you posted to make it into a library.

Ok, so I strted using the LED13 example on the arduino site. However it seems like it does not find it:

Arduino: 1.6.8 (Windows 10), Board: "Arduino Nano, ATmega328"

C:\Users\Kim\Documents\Arduino\test\test.ino:1:19: fatal error: LED13.h: No such file or directory

 #include <LED13.h>

                   ^

compilation terminated.

exit status 1
Error compiling for board Arduino Nano.
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim
Invalid library found in C:\Users\Kim\Documents\Arduino\libraries\Kim: C:\Users\Kim\Documents\Arduino\libraries\Kim

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

What am I missing?

I believe the library name (the folder name; Kim) has to be the same as the primary header file (LED13.h).

Put your library in a folder named LED13 instead of a folder named Kim.

[quote author=Coding Badly link=msg=2717874 date=1461006961] I believe the library name (the folder name; Kim) has to be the same as the primary header file (LED13.h).

Put your library in a folder named LED13 instead of a folder named Kim.

[/quote]

I put in C:\Users\kim\Documents\Arduino\libraries\Kim\LED13

skatun:
I put in C:\Users\kim\Documents\Arduino\libraries\Kim\LED13

Your library needs to be adjacent to the others in the libraries folder.

You cannot put in a subdirectory and expect it to be found at compile time.

So the moderator of this forum, could you please add this to the tutorial:

http://playground.arduino.cc/Code/Library

Libraries needs to be placed in subdirectory of the library file, not a nested subdirectory. The library folder can either be here: C:\Users\kim\Documents\Arduino\libraries or C:\ProgramFiles\Arduino\libraries.

There are tutorials on the web(such as adafruit) that creates classes inside the sketch, this is however not recommended.

Also change the header file in the example to include Arduino.h instead of Wprogram.h

Well thanks for the help guys, I will post my Powermeter library as soon as I have it ready.

There are tutorials on the web(such as adafruit) that creates classes inside the sketch, this is however not recommended.

This is not true. A rule of thumb I once saw posted by one of the guru's here:

If you need more than one copy of a function within a sketch, make it into a class.

If you want to share your function with more than one person, make it into a library.

When you finish your library please include documentation on how to use it including examples. so that people(especially beginners) don't have to study the files to be able to use it.

skatun: So the moderator of this forum, could you please add this to the tutorial:

No.

But you are welcome to update the Wiki yourself... http://playground.arduino.cc/ http://playground.arduino.cc/Main/Participate

[quote author=Coding Badly link=msg=2719343 date=1461086325] No.

But you are welcome to update the Wiki yourself... http://playground.arduino.cc/ http://playground.arduino.cc/Main/Participate

[/quote]

Ok, the tutorial is not updated here: http://playground.arduino.cc/Code/Library?action=edit

I have no grants to edit so that its compatible with the latest version of Arduino..(change Wprogram to arduino.h) thats why I asked if some of the moderator might want to change that one line of code in the tutorial. Since it was also the first hit on search in google I think its kinda important that the zip file that downloads is able to compile. I easily fixed it with a google search, because I thought it most likely was renaming of a class, but others might struggle with this. (At least what i saw in some forum post)

Hutkikz: This is not true. A rule of thumb I once saw posted by one of the guru's here:

I was just refereing to this:

PaulS: There are good reasons for isolating the implementation from the definition, and no reasons (other than laziness) for not isolating them.

So I tried to make my libray work, however i get this error message:

Build options changed, rebuilding all
Power:3: error: 'EnergyMeter' does not name a type

 EnergyMeter power1(1);//initialize an instance of the class

 ^

C:\Users\kim\AppData\Local\Temp\arduino_modified_sketch_708020\Power.ino: In function 'void setup()':

Power:6: error: 'power1' was not declared in this scope

   power1.present();

   ^

C:\Users\kim\AppData\Local\Temp\arduino_modified_sketch_708020\Power.ino: In function 'void loop()':

Power:10: error: 'power1' was not declared in this scope

   power1.update();

   ^

exit status 1
'EnergyMeter' does not name a type

My library can be found on github:

Any idea where the mistake in the constructor are?

Sorry for all these problems with my first class, I am used to VB and just got into writing more complex arduino code.

'EnergyMeter' does not name a type

Where do you define the EnergyMeter class?

Here I define it:

#include <EnergyMeter.h>

EnergyMeter power1(2);//initialize an instance of the class on node ID 2

void setup(){
  power1.present();

}

void loop(){
  power1.update();
}

That’s where you included it. Can we see the class definition?

When I look in your github at the EnergyMeter.h file I only see a definition of a LED13 class. There’s no EnergyMeter class there.

skatun: Here I define it:

No, there you try to instantiate a class object.

Where is the class defined? It isn't in your header.

You should post your code here... lots of folks won't go looking for it.

I think the problem is how variables are declared/initilazed:

Can I do this outside everything in the .cpp file?

boolean pcReceived = false;

Here is my energyMeter.cpp code:

#include "EnergyMeter.h" //include the declaration for this class


#include <SPI.h>
#include <MySensor.h>  

long PULSE_FACTOR       // Nummber of blinks per KWH of your meeter
boolean SLEEP_MODE        // Watt-value can only be reported when sleep mode is false.
long MAX_WATT          // Max watt value to report. This filetrs outliers.
int DIGITAL_INPUT_SENSOR // Usually the interrupt = pin -2 (on uno/nano anyway)
int CHILD_ID              // Id of the sensor child
unsigned long SEND_FREQUENCY
double ppwh

boolean pcReceived = false;
volatile unsigned long pulseCount = 0;   
volatile unsigned long lastBlink = 0;
volatile unsigned long watt = 0;
unsigned long oldPulseCount = 0;   
unsigned long oldWatt = 0;
double oldKwh;
unsigned long lastSend;


//<<constructor>> setup the LED, make pin 13 an OUTPUT
EnergyMeter::EnergyMeter(int _CHILD_ID){
	CHILD_ID   = _CHILD_ID;           // Id of the sensor child
	
	/* Optional Arguments */
	SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway.
	PULSE_FACTOR =1000;       // Nummber of blinks per KWH of your meeter
	SLEEP_MODE =  false ;       // Watt-value can only be reported when sleep mode is false.
	MAX_WATT = 10000;          // Max watt value to report. This filetrs outliers.
	DIGITAL_INPUT_SENSOR = 0; // Usually the interrupt = pin -2 (on uno/nano anyway)
	

	/*Starting the setup algorithm */
	ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour
	
	MyMessage wattMsg(CHILD_ID,V_WATT);
	MyMessage kwhMsg(CHILD_ID,V_KWH);
	MyMessage pcMsg(CHILD_ID,V_VAR1);
	
	// Fetch last known pulse count value from gw
	request(CHILD_ID, V_VAR1);

	// Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output
	// If no pullup is used, the reported usage will be too high because of the floating pin
	pinMode(DIGITAL_INPUT_SENSOR,INPUT_PULLUP);
	  
	attachInterrupt(INTERRUPT, onPulse, RISING);
	lastSend=millis();
}

//<<destructor>>
EnergyMeter::~EnergyMeter(){/*nothing to destruct*/}

//present it
void ENERGYMETER::present(){
    // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Energy Meter", "1.0");

  // Register this device as power sensor
  present(CHILD_ID, S_POWER);
}


//update the reading of the power
void ENERGYMETER::update(){
 
  unsigned long now = millis();
  // Only send values at a maximum frequency or woken up from sleep
  bool sendTime = now - lastSend > SEND_FREQUENCY;
  if (pcReceived && (SLEEP_MODE || sendTime)) {
    // New watt value has been calculated  
    if (!SLEEP_MODE && watt != oldWatt) {
      // Check that we dont get unresonable large watt value. 
      // could hapen when long wraps or false interrupt triggered
      if (watt<((unsigned long)MAX_WATT)) {
        send(wattMsg.set(watt));  // Send watt value to gw 
      }  
      Serial.print("Watt:");
      Serial.println(watt);
      oldWatt = watt;
    }
  
    // Pulse cout has changed
    if (pulseCount != oldPulseCount) {
      send(pcMsg.set(pulseCount));  // Send pulse count value to gw 
      double kwh = ((double)pulseCount/((double)PULSE_FACTOR));     
      oldPulseCount = pulseCount;
      if (kwh != oldKwh) {
        send(kwhMsg.set(kwh, 4));  // Send kwh value to gw 
        oldKwh = kwh;
      }
    }    
    lastSend = now;
  } else if (sendTime && !pcReceived) {
    // No count received. Try requesting it again
    request(CHILD_ID, V_VAR1);
    lastSend=now;
  }
  
  if (SLEEP_MODE) {
    sleep(SEND_FREQUENCY);
  }
}

}


void receive(const MyMessage &message) {
  if (message.type==V_VAR1) {  
    pulseCount = oldPulseCount = message.getLong();
    Serial.print("Received last pulse count from gw:");
    Serial.println(pulseCount);
    pcReceived = true;
  }
}

void onPulse()     
{ 
  if (!SLEEP_MODE) {
    unsigned long newBlink = micros();  
    unsigned long interval = newBlink-lastBlink;
    if (interval<10000L) { // Sometimes we get interrupt on RISING
      return;
    }
    watt = (3600000000.0 /interval) / ppwh;
    lastBlink = newBlink;
  } 
  pulseCount++;
}

here is my header file:

#ifndef EnergyMeter_H
#define EnergyMeter_H

#include "Arduino.h"

class EnergyMeter { 
public:
	EnergyMeter(int childId);
	~EnergyMeter();
    void present();
	void update();
};

#endif

and finally is my test sketch:

#include <EnergyMeter.h>

EnergyMeter power(1);//initialize an instance of the class

void setup(){
  power.present();
  }

void loop(){
  power.update();//stay one second on, then a second off
}
Here is my energyMeter.cpp code:

Did you bother trying to compile that before you posted it?

Why are you (trying) to define all those global variables in the source file? A class is SUPPOSED to encapsulate data, not provide more opportunities to screw things up.

By convention, all capital letter names are reserved for constants. Constants never appear on the left of an equal sign (except when first declared and valued).

PaulS: Here is my energyMeter.cpp code:

Did you bother trying to compile that before you posted it?

Yes, I compiled it and I get some error message that I am currently trying to sort out.

PaulS: Why are you (trying) to define all those global variables in the source file? A class is SUPPOSED to encapsulate data, not provide more opportunities to screw things up.

I am going to create 16 of these objects + 22 other objects in my sketch hence i would like to move every test sketch i have made to its own class instead of copying it in 38 times.

So whats the best way to define constant for an object, and the second thing how can I make constant shared between objects but still define them when i create the object?

PaulS: By convention, all capital letter names are reserved for constants. Constants never appear on the left of an equal sign (except when first declared and valued).

So these are all constants:

long PULSE_FACTOR       // Nummber of blinks per KWH of your meeter
boolean SLEEP_MODE        // Watt-value can only be reported when sleep mode is false.
long MAX_WATT          // Max watt value to report. This filetrs outliers.
int DIGITAL_INPUT_SENSOR // Usually the interrupt = pin -2 (on uno/nano anyway)
int CHILD_ID              // Id of the sensor child
unsigned long SEND_FREQUENCY

So when I create the object I want to initialize these CONSTANT that never changes in my update method which are called inside the loop in my main sketch.

Currently I only want to set CHILD_ID when I create the object, the rest of the constant should be optional.

Coming from vb background what I am used to is:

EnergyMeter power(CHILD_ID:=1,MAX_WATT=10000);//initialize an instance of the class

where I just specify which one of the optional parameter I would like to set.

So all these CONSTANT should be only constants for that object, but MAX_WATT and PULSE_FACTOR could be shared across objects, if they are not given as input the constructor for the objects.

I am trying to read up on how c++ threats constants, and what volatile do and what should be defined in the header file and what should be defined inside/outside the constructor. But I am a bit lost and the official class tutorial for arduino does not threat constants at all: http://www.arduino.cc/en/Hacking/LibraryTutorial

and these are variables(that changes in my update method) for the class object:(small letters..)

double ppwh

boolean pcReceived = false;
volatile unsigned long pulseCount = 0;   
volatile unsigned long lastBlink = 0;
volatile unsigned long watt = 0;
unsigned long oldPulseCount = 0;   
unsigned long oldWatt = 0;
double oldKwh;
unsigned long lastSend;

In normal arduino code you pub both variables and constant at the top of your sketch, however it seems to be different in cpp files.