Calling a class object in another class function.

Hi, i’m currently building a metering project and facing problem on making an interface between classes.
i have my sensor object run good and work as expected.

here the header file for my sensing library.

#ifndef Sensing_h
#define Sensing_h
#include "Arduino.h"
#include "Timer.h"

class Sensing {
private:	
    float anV, anI, anW, recordI=0, recordV=0, recordW=0, I, P, V, S, PF, F,Period;
	float freqsample[3];
	unsigned long peaktime[2];
    float MidPointI = 511.5;
    float MidPointV = 511.5;
    int readcount,iread, vread;
	byte pinI = A1, pinV = A0;
    void freqcalc();
    void setdata();
public:
    Sensing(byte pini, byte pinv): pinI(pini), pinV(pinv), sensor(1000) {}
    Timer sensor;
    void calibrate();
    void record();
    float getVrms();
    float getIrms();
    float getP();
    float getS();
    float getPF();
    float getF();
};
#endif

i’m currently doing my input/output class which will utilize an LCD (16x2) and a matrix keypad (3x4), along with LiquidCrystall and Keypad library included for the class. let’s say i’m making a class “ModIO” (who stands for Modded Input Output), and i want to make a paging function which will be initialized once in the setup function, and have pagenumber, x location, y location, entry. this paging function will save the locations(of the LCD cursor) and entry for each said pagenumber. the said entry can vary from char, numbers, or some class object function(or variable) returning some value. the said pagenumbers can be called with refresh function which will view(or update) the entries on the set location on the LCD.

here’s a brief example of what i want in my main code:

#include <Sensing.h>;
#include <Modio.h>;
#include <Timer.h>
Sensing sensor(1,0); //declaring a Sensing object and the analog pin to be used
Modio inout (/*some pin config for lcd and keypad*/);
Timer outrefresh(1000); //

void setup(){
  Serial.begin(9600); 
  Serial.println("calibrating");
  sensor.calibrate();
  inout.page(1, 0, 0, sensing.getVrms());
  Serial.println("calibrate done");
}

void loop(){
  sensor.record();
  if (outrefresh.gettimerstate()){    // refresh the page every 1 sec. 
    inout.refresh();                        
    outrefresh.starttimer(1000);      
  }
  //some other function to change the page
}

the question is:

  1. how can i do the paging function to record the functions(member of some other classes), so that the Modio can call it later with an updated value? (i’m full aware that with “paging(/…/, thefunction())” will set the current value returned by the function to the page and when called, the refresh function will view old “thefunction()” value).

  2. is it possible to “refresh” the value on the LCD regularly with a function inside the Modio class, without any line inside the loop function? (if it is, how to do it? is there any hints of what the thing is called, so that i can do a research?).

  3. does using “typedef struct” inside the Modio a wise method to record my pages (if not, what’s better for me to do it)?

any advice will be appreciated.

regards.

Sensing.cpp (1.63 KB)

Sensing.h (690 Bytes)

Timer.h (230 Bytes)

Timer.cpp (285 Bytes)

    Timer sensor;

Really? Is that any kind of meaningful name for an instance of a Timer class?

    unsigned long t, Interval;
  public:
	unsigned long T;

Variable names that differ only in case show a complete lack of imagination.

Sensing sensor(1,0); //declaring a Sensing object and the analog pin to be used

Which argument is THE analog pin? Is the other argument a decoration?

let’s say i’m making a class “ModIO” (who stands for Modded Input Output), and i want to make a paging function

There isn’t a hint in your code what this class might look like, derive from, etc.

So, only you have a clue what the paging function needs to look like.

But, I get the impression that it should be the base class, and other classes should derive from it. The derived classes are the only classes that know what it means to display page 12. The ModIO class should have virtual functions that the derived classes must implement.

PaulS:     Timer sensor;

Really? Is that any kind of meaningful name for an instance of a Timer class?

i don't know, i just think about it like a timer instance that work for the sensor stuff.

PaulS:     unsigned long t, Interval;   public: unsigned long T;

Variable names that differ only in case show a complete lack of imagination.

does it? i'm get used to differ the variable names by case when i recording two sample of them and plan to compare them later. in this case, t, which is in lower case, will have lower value (recorded earlier) compared to T, which is in upper case (recorded latter). in other case, where i need more than two samples to compare, i will use array type.

PaulS: Sensing sensor(1,0); //declaring a Sensing object and the analog pin to be used

Which argument is THE analog pin? Is the other argument a decoration?

both of them, one for Voltage sensor analog pin, and the other for Current sensor analog pin.

PaulS: There isn't a hint in your code what this class might look like, derive from, etc.

So, only you have a clue what the paging function needs to look like.

But, I get the impression that it should be the base class, and other classes should derive from it. The derived classes are the only classes that know what it means to display page 12. The ModIO class should have virtual functions that the derived classes must implement.

i'm really new to programming arduino (or C++), been doing this for like only 2 weeks. so neither i have the clue on what the paging function needs to look like.

i'm getting interested in building stuff with my arduino for my future project. so basically, i want this ModIO class built as a stand alone library, which is able to make a page based view on my LCD(set up page title, page format, some variable or function-returned value, etc), refresh the given value at timely interval (when needed), move between pages through my keypad input (show page x on LCD after the x button pressed), and make a numerical input (when needed, for example: manually change some variable for changing motor speed).

i plan to use this ModIO class as a library for my current and possible future project.so i (maybe?) need to make it a completely separated from my Sensing library.

this ModIO library (which is utilizing LiquidCrystal.h and Keypad.h libraries available from the Arduino IDE library manager) will have some function to: 1. set up pins used for the keypad and LCD, initialized when making an instance. 2. setting up pages to show with the parameter containing at least: page number, LCD x and y cursor position (something with the lcd.setcursor(x,y) function in LiquidCrystal library), and the thing to be shown on the said page and position. 3. making it possible for some of the page to ask for a number(or value) instead of viewing one. this should be able to be set in the page setting with some function overload. 4. when the shown value comes from a variable, function, or any other class member (Sensing member in my case), the ModIO library should be able to refresh/update the said value regularly.

  1. If possible (i don't think it is, and i thought i will giving up this one), i want to make the ModIO library able to do the refresh/update function (point 3) without any line on the loop function. and yes, i don't want noInterrupts in my code.

however, my main concern here is on point 2 and 4. tried several method (which is i don't fully understand) but nothing seems to works.

that's all i know about my soon to be ModIO. is that enough clue on what i want this ModIO to be? if so, can you help me with some reference i can access? or maybe some little example on how i can do this so that i can expand it? if the information is not enough, can you guide me on what's missing on my plan?

anyway, thanks a lot for your reply and sharing your words regarding my probably-weird-written code.

does it? i’m get used to differ the variable names by case when i recording two sample of them and plan to compare them later. in this case, t, which is in lower case, will have lower value (recorded earlier) compared to T, which is in upper case (recorded latter).

So, the values are olderT and newerT, not t and T. So, why not use names that make sense?

  1. If possible (i don’t think it is, and i thought i will giving up this one), i want to make the ModIO library able to do the refresh/update function (point 3) without any line on the loop function.

That is not possible. Somehow or other, your class instance(s) need to know that time has passed and that they might need to do something. That requires calling a method on each instance.

is that enough clue on what i want this ModIO to be?

It would not be enough for me to write the class.

PaulS:
So, the values are olderT and newerT, not t and T. So, why not use names that make sense?

who’s sense? yours? mine? that guys? this guys? or the “common” sense? or maybe there’s actually a rule for that?
in making variable, i’m kinda referencing the science (or math?) method on calling objects, at least those being taught here in my country. when there’s an older and newer “time”, we call them with “t” and “T” respectively. when there’s an older and newer velocity, we call the v and V respectively.
when there’s more than two records of an object, we called them x1, x2, x3, etc…
i even read a book about C++ programming for beginner. almost every variable used there have the “x” and “X” as the name. so, never come to my mind if my method to name the variable is bad or it doesn’t make sense.
so, in my case, t and T does make sense, at least it actually get to my sense. for the plus side, it is easier to avoid some typo in my code.
anyway, is there any hints, clues, or maybe some references for me to read, so i can understand the good variable naming method?

PaulS:
It would not be enough for me to write the class.

let’s short things up.
this is my main concern on my ModIO Class,

#include "LiquidCrystal.h"
#include "Timer.h"
class ModIO{
  public:
    ModIO():lcd(12, 11, 5, 4, 3, 2), InOutTimer(1000){
      lcd.begin(16,2);
}
    LiquidCrystal lcd;
    Timer InOutTimer;
    void pagesetup(/*what data type should i use?*/ /*should i use a pointer? no?*/{ //i don't even know how many parameter i needed here, but this function call is supposed to have some other class member function as a parameter
      //i don't know what i should do here, but it's supposed to store the said other-class-member function
    }

    void refresh(){
      if(InOutTimer.gettimerstate()){
        float thethingtobeupdated=thefunctionstoredinthepagesetupfunction; //this is supposed to get the updated value returned by the function, and store them to "thethingtobeupdated" variable.
        lcd.println(thethingtobeupdated);
    }
};

this is how i want my main code looks like:

#include <Sensing.h>
#include <ModIO.h>

Sensing sensor(1,0);
ModIO lcddisplay;

void setup(){
  sensor.calibrate();
  lcddisplay.pagesetup(&sensor.getVrms); //this is where i want the ModIO class to "remember" a function to call when the refresh function called.
}

void loop(){
  sensor.record();
  lcddisplay.refresh(); //this will refresh the value shown in the lcd every second.
}

is it good enough?
do you have any clues, hints or references regarding this subject?
if any, what should i provide to make it easier for you to help me?

anyway, is there any hints, clues, or maybe some references for me to read, so i can understand the good variable naming method?

I don’t have a reference I can give you. Only what I’ve learned over many years of programming.

First, mathematical notation is intended to be easy to write on paper or on a blackboard. Little squiggles, prime marks or greek letters are everywhere. In a computer program, you’re limited to the character set provided by your computer. Punctuation is used for syntax and operators, so you can’t put a prime on a variable name. That’s a quote mark. While the Arduino IDE does use Unicode and you could use greek letters in your variable names, that’s going to be a bad idea when you’re trying to get help here. Stick to standard ASCII.

The advantage of the compiler is that the variable names aren’t using up the precious Arduino memory. You can have a variable that’s hundreds of letters long. So you have free reign to put a long description into the name of every object and function.

So every variable or object instance should have a name that describes what it’s for. currentMillis, previousMillis, leftHandLowerDistanceSensorCentimeters or whatever.

Every function or method should have a name that describes what it does or what it returns. print(), update(), buttonWasPressed() or whatever. This gets very important with ‘simple’ boolean functions. Try to avoid ‘negative’ function names. Like userDidNotCancel(). That’s a poor name. If NotCancel returns true, then you should not do the cancel action so your if() statement will end up looking like if(!userDidNotCancel()) actionCancel(); and that little ‘!’ can easily get overlooked when you read it back later.

Capitalization is always a difficult subject. The basic rules to apply are that only constants should be ALLCAPS. With multiple words in the name, you are forced to put underscores to separate the words. ALL_CAPS, for example. Then functions and variables start out as lowercase. “sensor” and “temperature” for example. But with two words, the readability is enhanced by capitalizing the first letter of each word. Even if it’s a single letter word. “whatAVariable” for example.

For a while there was a craze called “Hungarian notation” which prepended the type of the variable to the variable name. “intTemperature”, for example. That may be useful for certain applications but you shouldn’t need to do it in an Arduino.

You are free to invent your own rules for capitalization or putting a verb first in a function name. But the goal is readability for the programmer, not to blindly follow rules.

Thanks a lot MorganS for the detailed explanation. i'll take a note for that. :) :) :)

Update.

in case my problem is not clear enough. here is what i want to do:

inside Modio header file:

#ifndef Modio_h
#define Modio_h
#include "Arduino.h"
#include "Timer.h"
#include "LiquidCrystal.h"

enum REFRESH{nonRefreshable,refreshable,inputmode};
template <class object, class member>
class Modio {
	struct PAGING {
		int xLoc;
		int yLoc;
		REFRESH refreshType;
		bool exist=false;
		char staticView;
		object objectAdress;
		member memberAdress;
	}page[12][32];
		int pageNumber;
		int entryNumber;
	public:
		Modio<object,member>(int Width, int Height): lcd(12, 11, 5, 4, 3, 2) {
			lcd.begin(Width, Height);
		}
		LiquidCrystal lcd;
		void pageSetup(int _pageNumber, int _xLoc, int _yLoc, char entry);
		void pageSetup(int _pageNumber, int _xLoc, int _yLoc, object _objectAdress, member _memberAdress);
		void printouts(int pageNumber);
};
template <class object, class member>

//the pageSetup function for setting up entry for each page
//------static/constant entry, non refreshable. typically used for page title or units
void Modio<object,member>::pageSetup(int _pageNumber, int _xLoc, int _yLoc, char entry){
	pageNumber=_pageNumber;
	entryNumber=0;
	while(!page[pageNumber][entryNumber].exist){
		entryNumber++;
	}
	page[pageNumber][entryNumber].xLoc=_xLoc;
	page[pageNumber][entryNumber].yLoc=_yLoc;
	page[pageNumber][entryNumber].staticView=entry;
	page[pageNumber][entryNumber].exist=true;
	page[pageNumber][entryNumber].refreshType=0;
}

//------refreshable entry, take some other class function as parameter 

template <class object, class member>
void Modio<object,member>::pageSetup(int _pageNumber, int _xLoc, int _yLoc, object _objectAdress, member _memberAdress){
	pageNumber=_pageNumber;
	entryNumber=0;
	while(!page[pageNumber][entryNumber].exist){
		entryNumber++;
	}
	page[pageNumber][entryNumber].xLoc=_xLoc;
	page[pageNumber][entryNumber].yLoc=_yLoc;
	page[pageNumber][entryNumber].objectAdress=_objectAdress;
	page[pageNumber][entryNumber].memberAdress=_memberAdress;
	page[pageNumber][entryNumber].exist=true;
	page[pageNumber][entryNumber].refreshType=1;
}

//print called page to lcd. once for each entry.

template <class object, class member>
void Modio<object,member>::printouts(int pageNumber) {
	lcd.clear();
	for (entryNumber=0; page[pageNumber][entryNumber].exist; entryNumber++){
		lcd.setCursor(page[pageNumber][entryNumber].xLoc, page[pageNumber][entryNumber].yLoc);

//------printing refresh-able entry

		if (page[pageNumber][entryNumber].refreshType=1){
			float P=(page[pageNumber][entryNumber].objectAdress)->*(page[pageNumber][entryNumber].memberAdress);
			lcd.println(P);
		}

//------printing non-refresh-able entry
		else{
			lcd.print(page[pageNumber][entryNumber].staticView);
		}
	}
}

//in progress writing a scheduled refresh function to refresh/re-print the refresh-able entry to lcd.

#endif

nothing inside the Modio.cpp since i have to put template body in a single file.

here’s my main code:

#include <Sensing.h>
#include <Modio.h>
unsigned long n = 0;
Sensing sensor(1, 0);
Timer Coba(1000);

typedef float (Sensing::*FloatSensingMember)();

//declaring a Modio class, using the Sensing class as reference for refresh-able entries. seting the pointer-to-object and pointer-to-member-function as the template data type.
Modio <Sensing*,FloatSensingMember> inout(16, 2);


void setup() {
  Serial.begin(9600);
  Serial.println("calibrating");
  sensor.calibrate();
  Serial.println("calibrate done");

//setting up pages.
//------setting up static, non-refresh-able page entry
  inout.pageSetup(0, 0, 0, "Voltage :");
//------setting up refresh-able page entry
  inout.pageSetup(0, 1, 0, &sensor, &Sensing::getVrms); //page, xLoc, yLoc, pointer-to-object, pointer-to-member-function
}

void loop() {
  n++;
  sensor.record();
  if (Coba.gettimerstate()) {
    Serial.println("--------------------------------------------------");
    Serial.print("|Voltage (v)    : ");
    Serial.println(sensor.getVrms());
    Serial.print("|Current (A)    : ");
    Serial.println(sensor.getIrms());
    Serial.print("|Power (Watt)   : ");
    Serial.println(sensor.getP());
    Serial.print("|Power (VA)     : ");
    Serial.println(sensor.getS());
    Serial.print("|Frequency (Hz) : ");
    Serial.println(sensor.getF());
    Serial.print("|Power Factor   : ");
    Serial.println(sensor.getPF());
    Serial.print("|Loop (Hz)      : ");
    Serial.println(n);

//printout the page 0 every 1 sec
    inout.printouts(0);
    n = 0;
    Coba.starttimer(1000);
  }
}

//in progress to add the looping function of Modio class for scheduling the refresh, and controlling the pageNumber to view

however, with this method, i get the error code

In file included from D:\Documents\Arduino\Script\Coba_coba\Coba_coba.ino:2:0:

D:\Documents\Arduino\libraries\Modio/Modio.h: In instantiation of ‘void Modio<object, member>::printouts(int) [with object = Sensing*; member = float (Sensing::*)()]’:

D:\Documents\Arduino\Script\Coba_coba\Coba_coba.ino:38:22: required from here

D:\Documents\Arduino\libraries\Modio/Modio.h:63:102: error: invalid use of non-static member function

float P=(page[pageNumber][entryNumber].objectAdress)->*(page[pageNumber][entryNumber].memberAdress);

^

Using library Sensing in folder: D:\Documents\Arduino\libraries\Sensing (legacy)
Using library Timer in folder: D:\Documents\Arduino\libraries\Timer (legacy)
Using library Modio in folder: D:\Documents\Arduino\libraries\Modio (legacy)
Using library LiquidCrystal at version 1.0.7 in folder: C:\Program Files (x86)\Arduino\libraries\LiquidCrystal
exit status 1
Error compiling for board Arduino/Genuino Uno.

does anyone know why i get the error?
can someone point out what i’ve missed here?

regards.