Arduino playing God...

Hey, because of not being able to return an array from a function, I decided to merge two different values into one and return that instead.
Those values are Temperature and Humidity.
Basically, I convert the Temperature and Humidity into ints (they're floats with 2 decimal places) by multiplying them by 100 and then I multiply the Temperature by 106 and then add the Humidity.
Eg: Temperature = 18.12ºC
Humidity = 83.10%
Result = 18128310

Here's some code:

for (int i=0; i < 5; i++) {
  receivedTemperature[i] = Serial.read();
}
    
for (int i=0; i < 5; i++) {
  receivedHumidity[i] = Serial.read();
}



float Temp, Hum;
if (receivedTemperatureSign == '+') {
  Temp = atof(receivedTemperature);
}
if(receivedTemperatureSign == '-') {
  Temp = -1 * atof(receivedTemperature);
}

Hum = atof(receivedHumidity);

unsigned long returningValue = Temp*1000000 + Hum*100;

Serial.print("Temp: "); Serial.println(Temp);
Serial.print("Hum: "); Serial.println(Hum);
Serial.print("returningValue: "); Serial.println(returningValue);
Serial.print("Temp*10^6: "); Serial.println(Temp*1000000);
Serial.print("Hum*100: "); Serial.println(Hum*100);

My input: 18.1283.10 [Temperature = 18.12 and Humidity = 83.10]
The output:
Temp: 18.13
Hum: 83.10
returningValue: 18136610
Temp10^6: 18128300.00
Hum
100: 8310.00

I don't know why, but it seems that, while Serial.reading, the receivedTemperature array is also appending part of the Humidity input.
BUT: I tried printing receivedTemperature[6] and it gave me nothing.

What's wrong with my code? :confused:

The problem is that you are assuming that floats store numbers as fixed precision decimals. The issue is a bit long to talk about in a forum post but you should read this:
http://docs.sun.com/source/806-3568/ncg_goldberg.html

simply (and imprecisely put) you are getting more sigfigs than you think. Just like 1/3 can't be represented in a finite number of digits in decimal, some decimal numbers get expanded out in floats.

IF you want to pack these numbers into one long you should cast them to integers first

eg

unsigned long returningValue = ((int)Temp*100)*10000 + (int)(Hum*100);

that said, its still not a great way to do it. the best thing to do is to put temp and hum into an array

eg

void returntwothings (float *things) {
    float thing1 = getthing();
    float thing2 = getthing();
    things[0] = thing1;
    things[1] = thing2;
    return;
}

and the caller should look like:

//....
float values[2];
returntwothings(values); 

//....

after these two lines values has thing1 and thing2.

Thanks a lot for both the incredible link and the last code block: it works perfectly.

Now, if I wanted to return values of different types (like an int, a float, a char and a boolean), could I still use that last code block of yours? I don't think so... :confused:

And is there any possible way for me to get 18.12 instead of 18.13? Like, I don't know, keeping only the two decimal places and "eliminating" the rest while NOT ROUNDING the last decimal place?

That last block does infact work. try this C++ code out on your PC

#include<iostream>

using namespace std;

void getTwoNumbers(float *f);

int main() {
        float f[2];
        f[0] = 1.1;
        f[1] = 1.2;
        cout << " f is: "<<f[0]<<" and "<< f[1] << endl;
        cout << "calling getTwoNumbers" << endl;
        getTwoNumbers(f);

        cout << "now f is: "<<f[0]<<" and "<< f[1] << endl;

        return 0;
}

void getTwoNumbers(float *f) {
        float f1, f2;
        cout << "give me a number: ";
        cin >> f1;
        cout << "give me another number: ";
        cin >> f2;
        f[0] = f1;
        f[1] = f2;
        return;

}

If you don't want to run it here's my computers output:

 f is: 1.1 and 1.2
calling getTwoNumbers
give me a number: 7.4
give me another number: 10.2
now f is: 7.4 and 10.2

Yes, yes: the function works perfectly! The only problem is that with my Arduino the returned value of the Temperature is 0.01 higher than the inputted Temperature. I subtracted those 0.01 and now the inputs and outputs match (go figure..).

I just wanted to know if it was possible to return more than one type at the same time... I'm still a newb, so sorry if this question seems trivial.. :confused: I just learned from the code you posted before what the '__*__var' actually meant.. So yeah.. :stuck_out_tongue:

You could return a structure.

good call. Using pointers is probably needlessly complicated for this. A structure would make the most sense here.

You can also use the reference operator in the function declaration, to define multiple return arguments:

void returnLotsOfStuff(int &arg1, float &arg2, float &arg3, float &arg4)
{
arg1 = 14;
arg2 = 1.75;
arg3 = -14.78;
arg4 = 100004.6789;
}

Of course, the arguments do not need to be hardcoded values.

The only drawback to this approach is that the compiler does not properly generate function prototypes for functions with reference arguments, but the function can be defined before it is called, and the prototype is not needed.