Looking for a concise way of finding the variable holding the largest value

Hello forum,

I put together a weather station and when dealing with wind direction I've decided to filter from the detected directions the one that was detected most between data upload times. The data is uploaded to my server every five minutes or so but I detect the speed and direction every few seconds between uploads and in order to filter out false direction values I want to only send the direction value that was detected most during the five minutes prior to uploading. Instead of just sending the last value before uploading. This is to hopefully cancel out false values due to swirling when the wind dies down.

Now my question: I need to write a function to determine which one of the 16 directions were detected most during the five minutes of measuring. I would be doing the tedious if (N > NNE && N > NE && N > ENE etc.etc.etc.) for each of the 16 directions, but I want to know from the experts if there's a quicker way of doing this in Arduino's version of C+, in the same way that NW = NW + 1; can be substituted by NW++;

Thanks,
Hein

Put the values in an array so you can use for loops to go through and compare them one by one.

Many people use a circular mean to calculate and represent the most common wind direction. That way you avoid the 0/360 problem.

Delta_G:
Put the values in an array so you can use for loops to go through and compare them one by one.

Thanks. Can you show me a basic example of how you'd do this?

jremington:
Many people use a circular mean to calculate and represent the most common wind direction. That way you avoid the 0/360 problem.

I was thinking about this and how to get an average on the circle continuum, but then I realised just picking the most common direction would be much simpler. If my wind vane measured the full circle as degrees I would have gone that route, but the model I have only outputs one of the 16 main directions anyway.

Please tell us your level of knowledge. Do you know how to declare an array? Do you know how to access an element of an array? Do you know how to use a for loop? Do you know about the circular mean? If you expect information, you should also be able to provide information.

heinburgh:
I was thinking about this and how to get an average on the circle continuum, but then I realised just picking the most common direction would be much simpler.

If you have enough memory to create an array that can hold all the values for your time interval (5 minutes) then use an index to make that a circular array. For every new reading advance the index and save the value at the new location, overwriting the value that was already there. That way you can always get the most popular value in the time period by iterating over the whole array. You could also get the average or any other statistic.

If you want to get the most popular value you may wish to massage the values so that, for example, 270 271 and 272 would be treated as the same - maybe only store values in steps of 5.

...R

Each of the sixteen directions corresponds to an angle so the circular mean could still be appropriate.

Searching for the direction with the most occurrences is still much easier if arrays are used. Long complicated error-prone if statements are not needed.

You’ve peaked my interest in the circular mean, I’ll certainly look into it a bit later.

For now I think I’ll do it like this: since the wind vane returns a value between 0 and 15 (0 being N, 1 being NNE, 3 being NE, etc.) these values fit in well with using an int array. So when the vane returns a value of 5, I increment windDirs[5] etc.

Every time the sketch checks wind speed and returns a positive value, it checks the current direction:

void Setup()
{
  uint8_t resultMain;  
  int vaneResult, windDirs[16];
}



void getWindDir()
{
  resultMain = node.readHoldingRegisters(0x0017, 1);
  
  if (resultMain == node.ku8MBSuccess) 
  {
    vaneResult = node.getResponseBuffer(0x00);
    Serial.print("VANE RESULT: ");
    Serial.println(vaneResult);

    for (int i = 0; i < 16; i++)
    {
      if (vaneResult == i)
        windDirs[vaneResult]++;
    }    
    getPopularDir();
  }
  
  else
    Serial.println(F(">>>>>  VANE RESULT BAD"));  
}

After each time a result is received from the vane I run a check to see which direction is the current popular one:

void getPopularDir()
{
  int popularDir, a, b;
  
  for (a = 0; a < 16; a++)      //   NOT TOO SURE IF THIS WILL WORK 100%
  {
    for (b = 0; b < 16; b++)
    {
      if (windDirs[a] >= windDirs[b])   
        popularDir = a;
    }
  }
 
 windDir = ""; 

 if (popularDir == 0)
   windDir = "N";

 if (popularDir == 1) 
   windDir = "NNE";

 if (popularDir == 2)
   windDir = "NE";  

 if (popularDir == 3)
   windDir = "ENE";

 if (popularDir == 4)
   windDir = "E";   

 if (popularDir == 5)
   windDir = "ESE"; 

 if (popularDir == 6)
   windDir = "SE"; 

 if (popularDir == 7)
   windDir = "SSE"; 

 if (popularDir == 8)
   windDir = "S"; 

 if (popularDir == 9)
   windDir = "SSW";

 if (popularDir == 10)
   windDir = "SW";  

 if (popularDir == 11)
   windDir = "WSW";     

 if (popularDir == 12)
   windDir = "W";  

 if (popularDir == 13)
   windDir = "WNW"; 

 if (popularDir == 14)
   windDir = "NW";  

 if (popularDir == 15)
   windDir = "NNW";  


 windDeg = float(popularDir * 22.5);

 Serial.print(F("POPULAR WIND DIRECTION: "));
 Serial.print(windDir);
 Serial.print(F(" || "));
 Serial.print(F("POPULAR WIND DEGREES: "));
 Serial.println(windDeg, 1);
 
}

I’ve not tested the code since I need to climb up to the weather station to do so - will have to wait until tomorrow morning.

Quicker and shorter:

int a, popularDir, b=0;
  for (a = 0; a < 16; a++)  {
  if (windDirs[a] > b ) {
     popularDir = a;
     b = windDirs[a];
  }
}

One advantage of the circular mean is that it can have higher resolution than the original data, as it averages between “compass points”.

Thank you sir!

jremington:
Quicker and shorter:

int a, popularDir, b=0;

for (a = 0; a < 16; a++)  {
  if (windDirs[a] > b ) {
    popularDir = a;
    b = windDirs[a];
  }
}




One advantage of the circular mean is that it can have higher resolution than the original data, as it averages between "compass points".

Curious why you assign zero value to b. Does it not automatically have value of zero when initiated?

No, the assignment is the initialisation.

Only globals and static variables are automatically zeroed.

jremington:
One advantage of the circular mean is that it can have higher resolution than the original data, as it averages between "compass points".

Excellent point. And for that reason I'll start working on this.

jremington:
Many people use a circular mean to calculate and represent the most common wind direction. That way you avoid the 0/360 problem.

These formulas are hectic - is the only to get this done to work them into my sketch in math formulas or is there a library that can take care of this?

Just sines and cosines -- high school trigonometry. Adds 2-3 lines of code.

Ten seconds of Googling found this discussion with code examples. I'll bet you could have done that too.

Exactly what I'm now doing.

You make high school trig sound easy. That was 20 years ago!

I don't know what you meant by "hectic". They seem pretty straightforward to me but I suppose that someone somewhere could have put this into a library.

Let's say that you have an old-fashioned balance scale, the kind with two pans. You put two things on the scale, one on each pan, and the scale will show you which one is heavier.
You also have 16 pumpkins. Your task is to use the scale to find the heaviest pumpkin. How do you do this?

First, you take any two pumpkins and weigh them against each other. This will tell you which of those two pumpkins is heavier. That pumpkin (the heavier of the first two pumpkins) then gets weighed against a third pumpkin. Now you know which of those first three pumpkins is the heaviest. Then weigh that pumpkin (the heaviest one of the first three pumpkins) against a fourth pumpkin, etc. Notice that each new pumpkin only gets weighed against one of the previous pumpkins, not against all of them. So, for 16 pumpkins, you only need 15 weighings.

You make high school trig sound easy. That was 20 years ago!

In high school, did you think trigonometry was useless and a waste of time?