Nested Functions/Functions as a Parameter for a function

Hello,
i am trying to shrink my code from this:

[code]
 //PT1
  digitalWrite(cs1, LOW); 
  uint16_t rtd1 = max_1.readRTD();
  float ratio1 = rtd1;
  ratio1 /= 32768;
  pt1=max_1.temperature(100, RREF);
  Serial.println(pt1);
  digitalWrite(cs1, HIGH); 
//PT2  
  digitalWrite(cs2, LOW); 
  uint16_t rtd2 = max_2.readRTD();
  float ratio2 = rtd2;
  ratio2 /= 32768;
  pt2=max_2.temperature(100, RREF);
  Serial.println(pt2);
  digitalWrite(cs2, HIGH);
//PT3
  digitalWrite(cs3, LOW); 
  uint16_t rtd3 = max_3.readRTD();
  float ratio3 = rtd3;
  ratio3 /= 32768;
  pt3=max_3.temperature(100, RREF);
  Serial.println(pt3);
  digitalWrite(cs3, HIGH); 
//PT4
  digitalWrite(cs4, LOW); 
  uint16_t rtd4 = max_4.readRTD();
  float ratio4 = rtd4;
  ratio4 /= 32768;
  pt4=max_4.temperature(100, RREF);
  Serial.println(pt4);
  digitalWrite(cs4, HIGH);

[/code]

to this:

[code]
    float readTemp(cs1, rtd1, max_1.readRTD, ratio1, pt1, max_1.temperature);
    float readTemp(cs2, rtd2, max_2.readRTD, ratio2, pt2, max_2.temperature);
    float readTemp(cs3, rtd3, max_3.readRTD, ratio3, pt3, max_3.temperature);
    float readTemp(cs4, rtd4, max_4.readRTD, ratio4, pt4, max_4.temperature);
[/code]

The problem currently is here as i try to declare a function with a function as a parameter, and that
does not not work like this.

[code]
void readTemp(int a, uint16_t b, uint16_t c, float d , float e, uint16_t f){
  digitalWrite(a, LOW); 
  b  = c;
  d  = b;
  d /= 32768;
  e  = f(100, RREF);
  Serial.println(e);
  digitalWrite(a, HIGH);
}
[/code]

i get " 'f' cannot be used as a function" error which has to do with pointers i believe but i cant solve it.
Note that i want help with the structure of the functions and the declaration of them and the board is irrelevant as the first/analytical code that i posted is actually working :
This is the whole sketch.

[code]
//#include "SoftwareSerial.h"
#include "SPI.h"
#include "DHT.h"
#include "MS5611.h"
#include "Wire.h"
#include <Arduino.h>
#include <ArduinoJson.h>
#define DHTPIN 40 
#define DHTTYPE DHT22 
#define P0 1013.25
#include <Adafruit_MAX31865.h>
#define RREF      430.0

// The 'nominal' 0-degrees-C resistance of the sensor
// 100.0 for PT100, 1000.0 for PT1000
#define RNOMINAL  100.0

const int cs1=11,cs2=12,cs3=13,cs4=17;
float t=0,h=0,pt1=0,pt2=0,pt3=0,pt4=0;
long  realPressure;
double referencePressure;

DHT dht(DHTPIN, DHTTYPE);
//MS5611
MS5611 ms5611;
//PT100-MAX31865 SETUP
// use hardware SPI, just pass in the CS pin
Adafruit_MAX31865 max_1 = Adafruit_MAX31865(cs1);
Adafruit_MAX31865 max_2 = Adafruit_MAX31865(cs2);
Adafruit_MAX31865 max_3 = Adafruit_MAX31865(cs3);
Adafruit_MAX31865 max_4 = Adafruit_MAX31865(cs4);

void readTemp(int a, uint16_t b, uint16_t c, float d , float e, uint16_t f){
  digitalWrite(a, LOW); 
  b  = c;
  d  = b;
  d /= 32768;
  e  = f(100, RREF);
  Serial.println(e);
  digitalWrite(a, HIGH);
}

void setup(void){  
  Serial.begin(9600);
  Serial1.begin(9600);
  SPI.begin();
  dht.begin(); 
  u8g2.begin();
  u8g2.clearDisplay();
  ms5611.begin();
  referencePressure = ms5611.readPressure();
  max_1.begin(MAX31865_3WIRE);
  max_2.begin(MAX31865_3WIRE);
  max_3.begin(MAX31865_3WIRE);
  max_4.begin(MAX31865_3WIRE); 
}
void loop() {

//dht22
  h = dht.readHumidity();
  t = dht.readTemperature();
    delay(1000);
//MS5611
  // Read raw values
  uint32_t rawPressure = ms5611.readRawPressure();
  // Read true Pressure
  realPressure = ms5611.readPressure();


    float readTemp(cs1, rtd1, max_1.readRTD, ratio1, pt1,max_1.temperature);
    float readTemp(cs2, rtd2, max_2.readRTD, ratio2, pt2,max_2.temperature);
    float readTemp(cs3, rtd3, max_3.readRTD, ratio3, pt3,max_3.temperature);
    float readTemp(cs4, rtd4, max_4.readRTD, ratio4, pt4,max_4.temperature);


StaticJsonBuffer<1024> jsonBuffer;
JsonObject& data = jsonBuffer.createObject();

//Assign collected data to Json Object
data["humidity"]    = h;
data["temperature"] = t;
data["pt1"]         = pt1;
data["pt2"]         = pt2;
data["pt3"]         = pt3;
data["pt4"]         = pt4;
data["pressure"]    = realPressure;


//Send data to NodeMCU
data.printTo(Serial1);
jsonBuffer.clear();

 
Serial.println(pt1);
Serial.println(pt2);
Serial.println(pt3);
Serial.println(pt4);
  delay(1000);

}
[/code]

Thanks in advance,
Gio.

Here's a tutorial on Function Pointers. You can do a search on that term to find others.

1 Like

i have already checked a ton about pointers, functions, references and the operators before posting here. This is actually my first time posting here, but ill check this right away, maybe i get the solution.

thanks gfvalvo

For your problem you don't need function pointers.
Instead of putting max_1.readRTD and max_1.temperature as parameters you can transfer to function the pointer to max_1 object and call it methods inside.

looks like readTemp() expects a float value, "f", and "max_1.temperature" is a function pointer.

don't you want to pass the float returned by "max_1.temperature()"

needs arguments

 float temperature(float RTDnominal, float refResistor);
2 Likes

exactly, i want to pass the float returned by "max_1.temperature()" but its a function pointer. How am i implementing this?

could you show me the place i need to assign the arguments?i mean if i put them upon calling the function or before that as a separate declaration?
Thanks @gcjr , @b707 for answearing and helping me so fast gentlemen!

can you show me what you mean by that?

How the variable max_1 is defined in the code?

max_1 is not defined in this code other than

Adafruit_MAX31865 max_1 = Adafruit_MAX31865(cs1);

which is passing a pin in reality (as i am using hardware SPI (Vin, Ground, clock, miso, mosi))
because it is derived from this library:

#include <Adafruit_MAX31865.h>```

i don't believe it's a function ptr, it's a method of Adafruit_MAX31865. so call the function in the call to readTemps(). the readTemps() will be invoked with the return value of max_1.temperature (... needs arguments ...))

sure it is

#include <Adafruit_MAX31865.h>
...
Adafruit_MAX31865 max_1 = Adafruit_MAX31865(cs1);
...
    float readTemp(cs1, rtd1, max_1.readRTD, ratio1, pt1,max_1.temperature);

are all in the same file

You cannot create a pointer to a class/struct member function. That simply won't work. Perhaps you might be able to do what you want using lambda functions.

instead of this

you can define the function

float readTemp(int cs_pin, uint16_t &rtd,  float &ratio , float &pt, Adafruit_MAX31865 &max){
  digitalWrite(cs_pin, LOW);
  rtd = max.readRTD();
  ratio = rtd/32768;
  pt=max.temperature(100, RREF);
  Serial.println(pt);
  digitalWrite(cs_pin, HIGH);
}

and use it as

temp1 = readTemp(cs1, rtd1, ratio1, pt1, max_1);

I don't see - are the variables ratio1, ratio2 ... and rtd1 .. rtd4 used anywhere in code outside of this block? if not - you shouldn't pass it as parameters in the function - make it local variables instead.

Right, I suggested function pointers too quickly before checking code and seeing OP was using member functions.

This is a much better way (but I'd use a Reference to the object rather than a pointer):

tried this:

and i get " 'rtd' was not declared in this scope" , then changed this

temp1 = readTemp(cs1, rtd1, ratio1, pt1, max_1);

to rtd (instead of rtd1),same.

as i understand these are all unique variables for each sensor, and they are used inside the library and not in the code.
Unique in sense of being calculated every time the loop starts again, rather than being constants.

The only thing wrong here

 float readTemp(cs1, rtd1, max_1.readRTD, ratio1, pt1, max_1.temperature); float readTemp(cs2, rtd2, max_2.readRTD, ratio2, pt2, max_2.temperature); float readTemp(cs3, rtd3, max_3.readRTD, ratio3, pt3, max_3.temperature); float readTemp(cs4, rtd4, max_4.readRTD, ratio4, pt4, max_4.temperature); 

Is missing () after readRTD and temperature.
The missing () makes it a function pointer, but you do not want a pointer. Instead you want to substitute the result of this function as an argument. The () will cause the function to return a value that is substituted as an argument.

please show all the code

You can with this non standard gcc extension.

For example:

class C {
public:
  void print() {
    Serial.println("Hi.");
  }
};

void test(C& obj, void (C::*f)()) {
 (obj.*f)();
}

void setup() {
  Serial.begin(9600);

  C c;
  test(c, &C::print);  // Prints "Hi.".
}

Not that this is a suitable solution for the problem at hand of course. I would go for the approach explained in post #14.

1 Like

But you still have to specify the object.