Returning several values obtained in a function

I have a function that calculates the values of different CTs connected to my equipment. How can I return the values of different CTs from that function every time I ask? Not too proficient in programming.

In my project I have several CT connected to different analog ports, so the function I created, calculate the values of CT1, CT2, CT3, CT4, ..ect.
At different times of my program I want to return different values of CT ( CT1, CT2...etc)

See this: http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/

What about using global variables so there is no need to return anything?

...R

Robin2:
What about using global variables so there is no need to return anything?

...R

Robin2:
What about using global variables so there is no need to return anything?

...R

I did that and does not work.

guix:
See this: http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/

Can't see how this can be applied to what I was looking for.

josegg:
I did that and does not work.

Post your code so we can see how it did not work.

...R

I did that and does not work.

Then you did it wrong. (Probably by having local variables with the same name as the global ones, but that's just a guess.)

Robin2:
Post your code so we can see how it did not work.

...R

This is the code.

#include "EmonLib.h"

EnergyMonitor Phase1; //50A
EnergyMonitor Phase2; //50A
EnergyMonitor Phase3; //50A
EnergyMonitor BRBed1; //10A
EnergyMonitor BRBed2; //10A
EnergyMonitor MicroW; //breaker 10 - 20A
EnergyMonitor Stove; //breaker 4 - 50A
EnergyMonitor AirC; //breaker 16 - 10A
EnergyMonitor BR7; //washer breaker 7 - 10A
EnergyMonitor BR14; //dishwasher breaker 14 - 10A

double TotalPower, MWload, STload, ACload, sensor =0;
double BR7load, Bed2load, Bed1load, BR14load =0;

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

Phase1.current(13, 30.6); // Phase 1 - Current: input pin, calibration.
Phase2.current(14, 30.6); // Phase 2 - Current: input pin, calibration.
Phase3.current(15, 30.8); // Phase 3 - Current: input pin, calibration.
BRBed1.current(0, 6.06); // Bedroom 1 heater
BRBed2.current(1, 6.06); // Bedroom 2 heater
BR7.current(6, 6.06); // Breaker 7 - wahing machine
BR14.current(7, 6.06); // Breaker 14 - dishwasher
Stove.current(8, 30.6); // Stove - Current: input pin, calibration.
MicroW.current(9, 11.0); // Microwave - braeaker 10
AirC.current(10, 6.06); // A/C - breaker 16

}

void loop() {

double Bed2load=SensorsRead();

Serial.println(Bed2load);

}

double SensorsRead() {
double Irms1 = Phase1.calcIrms(1480); // Calculate Irms only
double Irms2 = Phase2.calcIrms(1480); // Calculate Irms only
double Irms3 = Phase3.calcIrms(1480); // Calculate Irms only
double Bed1load = BRBed1.calcIrms(1480)*230.0;
double Bed2load = BRBed2.calcIrms(1480)*230.0;
double MWload = MicroW.calcIrms(1480)*230.0;
double STload = Stove.calcIrms(1480)*230.0;
double ACload = AirC.calcIrms(1480)*230.0;
double BR7load = BR7.calcIrms(1480)*230.0;
double BR14load = BR14.calcIrms(1480)*230.0; //Dishwasher
double TotalPower = (Irms1+Irms2+Irms3)*230.0;
Serial.print("Inside of SensorsRead ");
Serial.println(Bed2load);
}
Iniside of the function prints OK, but does return 0.00 although the variable is global.

Iniside of the function prints OK, but does return 0.00 although the variable is global.

void loop() {

double Bed2load=SensorsRead();

Really? Bed2load looks local to me.

In fact, it is local here, too:

double SensorsRead() {
   double Irms1 = Phase1.calcIrms(1480);  // Calculate Irms only
   double Irms2 = Phase2.calcIrms(1480);  // Calculate Irms only
   double Irms3 = Phase3.calcIrms(1480);  // Calculate Irms only
   double Bed1load = BRBed1.calcIrms(1480)*230.0;
   double Bed2load = BRBed2.calcIrms(1480)*230.0;

Having local and global variables with the name name is s.... (Help me out here, what's the word I'm thinking of? Opposite of smart. 6 letters...)

PaulS:

void loop() {

double Bed2load=SensorsRead();



Really? Bed2load looks local to me.

In fact, it is local here, too:


double SensorsRead() {
  double Irms1 = Phase1.calcIrms(1480);  // Calculate Irms only
  double Irms2 = Phase2.calcIrms(1480);  // Calculate Irms only
  double Irms3 = Phase3.calcIrms(1480);  // Calculate Irms only
  double Bed1load = BRBed1.calcIrms(1480)*230.0;
  double Bed2load = BRBed2.calcIrms(1480)*230.0;



Having local and global variables with the name name is s.... (Help me out here, what's the word I'm thinking of? Opposite of smart. 6 letters...)

I'm too proficient in programing. I do not see it. Could you please explain how can I extract any of the variables from the function?

Could you please explain how can I extract any of the variables from the function?

An example:

   double Bed2load = BRBed2.calcIrms(1480)*230.0;

creates a local variable and assigns it a value.

   Bed2load = BRBed2.calcIrms(1480)*230.0;

assigns a value to a global variable.

PaulS:
An example:

   double Bed2load = BRBed2.calcIrms(1480)*230.0;

creates a local variable and assigns it a value.

   Bed2load = BRBed2.calcIrms(1480)*230.0;

assigns a value to a global variable.

Eliminating the declaration of the variable in the loop section, which has been declared globally earlier in the programs and only calling the function, I see the return, but when compiling the program I get the following error:
"Invalid library found in C:\Program Files (x86)\Arduino\libraries\Firmata: Library can't use both 'src' and 'utility' folders".

Some ideas?

Some ideas?

Use a smarter version of the IDE. 1.0.5 comes to mind.

I think guix gave you a good answer. If you make the variables global, everything in the source code file has access to those variables from the point of their definition to the end of the file. This complicates debugging because the bogus value could have happened anywhere in the file. If you use pointers, you can hide the data within a function (e.g., encapsulation) yet still allow some other function to change their values.

Consider this program:

void setup() {
  int a = 5;
  int b = 10;
  int c = 20;
  
  Serial.begin(9600);
  Serial.print(" a = ");
  Serial.print(a);
  Serial.print("   b = ");
  Serial.print(b);
  Serial.print("   c = ");
  Serial.println(c);
  ChangeMultipleValues(&a, &b, &c);
   Serial.print("a = ");
  Serial.print(a);
  Serial.print("   b = ");
  Serial.print(b);
  Serial.print("   c = ");
  Serial.println(c);
}

void ChangeMultipleValues(int *x, int *y, int *z)
{
  *x = *x + 10;
  *y = *y + 10;
  *z = *z + 10;
}

void loop() {

}

Every variable has an lvalue and an rvalue. The lvalue is the memory address where a variable "lives" in memory while the rvalue is what's stored there. In a regular function call where you want to pass a value in, as in:

   int j;

   j = 10;
   myFunction(j);

Now suppose that j lives in memory at address 200, its lvalue. To assign the value 10, the compiler goes to j's lvalue and changes its rvalue to 10. Because Arduino int's take two bytes, the rvalue 10 must "fit" within those two bytes. When you call myFunction(), the compiler fetches j's lvalue, makes a copy of its rvalue (10), and passes it to the function. Note that the function has no clue of j's lvalue, only its rvalue.

Now change the last statement to:

   myFunction(&j);   // Pass the memory address of j--its lvalue--not a copy of its rvalue

Note the "address of" operator, &. This says to the compiler: "Instead of making a copy of the rvalue of j, send it's lvalue instead". So, the number 200 is sent to the function, not 10. In the function, the first line says:

void ChangeMultipleValues(int *x, int *y, int *z)

Instead of sending you copies of the variables, I'm giving you their addresses in memory (i.e., their lvalues). The statements within the function use the process called indirection to go to those memory addresses and permanently change the rvalues found there.

Because you sent the address of the variables to the function, the compiler needs to know its working with lvalues, not rvalue as is the norm. That what the indireciton operator (i.e., the '*') tells the compiler. So instead of using the rvalues of a, b, and c directly, it uses their lvalues to find where the "real" variables live in memory and then changes their values.

Besides the reference mentioned here, you can Google "pointers in C" and read much more.

Post the revised code that is giving the error and tell us what version of the Arduino IDE you are using.

I can't see why removing "double" from the line

  double Bed1load = BRBed1.calcIrms(1480)*230.0;

would cause an error on its own.

I guess you could always try a two-step process with this sort of thing in your function

  double bb1 = BRBed1.calcIrms(1480)*230.0;
   Bed1Load = bb1;

...R

I can't see why removing "double" from the line ... would cause an error on its own.

It didn't. There was obviously (to me, anyway) a change in versions of the IDE, too.

Though why anyone would do that in the middle of trying to debug some code is a real mystery.

PaulS:
Use a smarter version of the IDE. 1.0.5 comes to mind.

I'm running 1.6.5 IDE

Robin2:
Post the revised code that is giving the error and tell us what version of the Arduino IDE you are using.

I can't see why removing "double" from the line

  double Bed1load = BRBed1.calcIrms(1480)*230.0;

would cause an error on its own.

I guess you could always try a two-step process with this sort of thing in your function

  double bb1 = BRBed1.calcIrms(1480)*230.0;

Bed1Load = bb1;




...R

OK. More code

econjack:
I think guix gave you a good answer. If you make the variables global, everything in the source code file has access to those variables from the point of their definition to the end of the file. This complicates debugging because the bogus value could have happened anywhere in the file. If you use pointers, you can hide the data within a function (e.g., encapsulation) yet still allow some other function to change their values.

Consider this program:

void setup() {

int a = 5;
  int b = 10;
  int c = 20;
 
  Serial.begin(9600);
  Serial.print(" a = ");
  Serial.print(a);
  Serial.print("  b = ");
  Serial.print(b);
  Serial.print("  c = ");
  Serial.println(c);
  ChangeMultipleValues(&a, &b, &c);
  Serial.print("a = ");
  Serial.print(a);
  Serial.print("  b = ");
  Serial.print(b);
  Serial.print("  c = ");
  Serial.println(c);
}

void ChangeMultipleValues(int *x, int *y, int *z)
{
  *x = *x + 10;
  *y = *y + 10;
  *z = *z + 10;
}

void loop() {

}




Every variable has an lvalue and an rvalue. The lvalue is the memory address where a variable "lives" in memory while the rvalue is what's stored there. In a regular function call where you want to pass a value in, as in:



int j;

j = 10;
  myFunction(j);




Now suppose that j lives in memory at address 200, its lvalue. To assign the value 10, the compiler goes to j's lvalue and changes its rvalue to 10. Because Arduino *int*'s take two bytes, the rvalue 10 must "fit" within those two bytes. When you call *myFunction()*, the compiler fetches *j*'s lvalue, *makes a copy of its rvalue (10)*, and passes it to the function. Note that the function has no clue of j's lvalue, only its rvalue.

Now change the last statement to:



myFunction(&j);  // Pass the memory address of j--its lvalue--not a copy of its rvalue




Note the "address of" operator, &. This says to the compiler: "Instead of making a copy of the rvalue of j, send it's lvalue instead". So, the number 200 is sent to the function, not 10. In the function, the first line says:



void ChangeMultipleValues(int *x, int *y, int *z)




Instead of sending you copies of the variables, I'm giving you their addresses in memory (i.e., their lvalues). The statements within the function use the process called indirection to go to those memory addresses and permanently change the rvalues found there. 

Because you sent the address of the variables to the function, the compiler needs to know its working with lvalues, not rvalue as is the norm. That what the indireciton operator (i.e., the '*') tells the compiler. So instead of using the rvalues of a, b, and c directly, it uses their lvalues to find where the "real" variables live in memory and then changes their values.

Besides the reference mentioned here, you can Google "pointers in C" and read much more.

I'm always lost with this part of programing, and unless I understand completely (which I don't) I would prefer to stay away from it. I do not know how to implement that into my program. Looking at your code I can follow it but I don not know how to translate to my program.

...unless I understand completely (which I don't) I would prefer to stay away from it.

Not an uncommon reaction because pointers are one of the most difficult aspects of C programming to master. However, avoiding pointers dooms you to be a less than competent C programmer. Avoiding pointers is like trying to tie your shoes with one hand even though you have two.