Calling a function containing arrays for multiples sensors

Hello everyone,

I would just like to ask a general question:

I have serveral sensors for temperature and humitity. I want to calculate the average of the temperatures and humitities.

Is it possible to use just one function for the average calculations even if it contains arrays? Or will the data of one sensor overwrite the array of another?

I had something in mind like the following loop() and average() functions, as it is just a general question I wont be posting the setup():

Basic loop (I know its not complete):

void loop() {
sensors.requestTemperatures(); // read temperatures of both DS18B20 and DHT
valueDHT = dht[OUTTEMP].readTemperature(); // DHT Out
averageDHT = average(valueDHT);

}//loop

Average() with the corresponding setup():

const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
float total = 0;                  // the running total
float average = 0;                // the average

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

float average(const float &sensordata)
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = sensordata;
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(average);
  delay(1);        // delay in between reads for stability

  return average;

Thank you all!

Cheers,

Moses

If you pass the array to the average() function, that array will be distinct from any other array.

If you have average() use some global array, that array will be used for averaging all sensors - that is, you'll get garbage as the average.

Thank you PaulS

So I would define an array in the other function per sensor. But how would I pass it to the average() function? Would I pass the array and the sensordata seperately?

for example:

average(sensorArray[], sensorData);

What does the function have to look like? Something like this?

float average(const float &array, const float &data){
// instead of "readings" I would put the array? Here the example for the line "read from sensor":
array[readIndex] = data;

Thanks again

moses

There are several hiccups in your code. See if this works:

#define DEBUG                   // Comment out when done debugging

const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
float total   = 0.0;            // the running total

void setup() 
{
#ifdef DEBUG
  Serial.begin(9600);
#endif         
                                                      // initialize all the readings to 0:
  memset(readings, 0, sizeof(float) * numReadings);   // Little faster
}

void loop() {
  sensors.requestTemperatures();                // read temperatures of both DS18B20 and DHT
  valueDHT = dht[OUTTEMP].readTemperature();    // DHT Out
  averageDHT = average(valueDHT);

}//loop

float average(const float &sensordata)   // Is this really an lvalue?? 
{                                   // Your code doesn't have the opening brace
  total -= readings[readIndex];          // subtract the last reading:

  readings[readIndex] = sensordata;      // Replace with sensor data:
  total += sensordata;                          
  
  if (readIndex < numReadings - 1) {       
    readIndex++;
  } else {
    readIndex = 0;
  }

#ifdef DEBUG
  Serial.print("average = ");
  Serial.println(total / (float) numReadings);
  delay(1);        // delay in between reads for stability
#endif

  return total / (float) numReadings;;    // Return average
}

Hello econjack

Thank you for your inputs.

The code wasns't fully elaborated, because I was short of time. It was manly to know how to handle the array question while passing variables to a function.

My main goal:

  1. pass the sensor data to the function
  2. store the average in an array to calculate the running average
  3. return the average

Is I heared from PaulS I would have to pass the whole array to the funtion in order to not have a chaos. As I am writing I realize that I probably would better pass the array by value instead of reference to have the function modify it directly or would the function handle several arrays passed by reference as individual arrays and return the according averages?

After that I have understood the array issue I would like to:

  1. have a longtime or total average
  2. seperate daytime and nighttime averages
  3. understand if I can modify or work on an array with another array

Thank you.

moses

moserroger:
As I am writing I realize that I probably would better pass the array by value instead of reference to have the function modify it directly

You have that backwards. The conventional way to pass an array to a function is to pass a pointer to its first element along with the total number of elements it contains. The name of an array is implicitly cast as this pointer when you use it in a function call. The sizeof() compiler directive can help you determine the number of elements:

float myArray[10];
const uint8_t numElements = sizeof(myArray) / sizeof(myArray[0]);

void setup() {
}

void loop() {
  myFunction(myArray, numElements);
}

void myFunction(float theArray[], uint8_t arraySize) {
  for (uint8_t i=0; i<arraySize; i++) {
    // do stuff with array element theArray[i] here
  }
}

EDIT:
Of course the above is not at all necessary if the array is global and it's the only array you need the function to operate on.

Hello gfvalvo

thank you for the information.

I dont quite understand how the sizeof compiler directive works. Why is it devided by sizeof(myArray[0])?

Thank for the reply and clarification.

I tried it this way (just a sample code to test the concept):

int total = 0;
int numReadings = 10;
float average = 0.0;
 
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); // for debugging

 float test [numReadings] {2.0, 4.0, 6.0, 8.0, 9.0, 3.0, 4.0, 8.0, 2.0, 7.0 }; // should be 5.3

averageMath(test);

  float result = average;
    Serial.print("result: ");
    Serial.println(result);
}//setup
float averageMath(float Readings[]){
  for (int i = 0; i < numReadings; i++){
    total = total + Readings[i];
          }//for
    return average = total / numReadings;

  }//averageMath


void loop() {
  // put your main code here, to run repeatedly:

}

It seems to work. The only thing is that it returns 5.00 instead of 5.3. Where does this come from? Would this also be an acceptable way of doing it?

Cheers,

moses

I dont quite understand how the sizeof compiler directive works. Why is it devided by sizeof(myArray[0])?

sizeof() returns the number of bytes used by whatever is passed as a parameter, not the number of elements in an array. So using it to find the number of bytes allocated to an array and dividing it by the number of bytes used by one element of the array gives the number of elements in the array.

This will work with any data type even though different data types require different amounts of storage

sizeof tells you how large something is, in bytes. You have an array of ten floats at four bytes apiece so forty bytes. You need to divide by four then if you're trying to get the number of elements in the array. It's a common idiom to use the sizeof the first element in the array so that you don't have to hard code the divisor.

Your average is wrong because total and numReadings are integers, so the division is integer division, so that what should be 5.3 is truncated to 5.0 before you try to store it in a float.

Thank you UKHeliBob and wildbill this helped a lot

It's important that you understand that the default behavior for passing an array to a function is by reference. That means the function actually receives the starting memory address of where the array is stored. The only way that I can think of to pass an array by value is to put it in a structure and pass the structure...not a common way of working with arrays.