Checking fluctuating variables using thresholds, the smart way.

So, here’s the drill. In CS, we frequently need to check a variable compared to a predefined threshold.

Typical uses include checking the light level in a room and controlling the lights when it exceeds or goes below a certain threshold (the same can be done with temperature, essentially like a thermostat), checking the negative votes (vote-downs) for a post and removing it if it exceeds a threshold, e.t.c.

That’s usually easy to do programatically:

if(downvotes > VOTES_THRESHOLD)
{
remove_vote();
}

However, when you work with fluctuating variables, it’s harder to do a proper check. This is a common problem with sensor values, because they tend to fluctuate a lot. Consider the following example:

We use a light sensor whose values range from 0 to 255. Due to the nature of the sensor, the light value might fluctuate by +/-10 every time we read its value. We cannot simply use a threshold and check wether our input exceeds the threshold, because our value may fluctuate at that point. For instance, if we set our threshold to 120, and our input is at 115 (therefore below the threshold), due to its fluctuation we could get an input of 115-135. When we read the sensor, sometimes our value may be incorrectly considered by our software as above the threshold. So what do we do? The simple answer is that we can move the threshold higher. However, that has two disadvantages:

  1. Moving the threshold is sometimes not possible, because then we could miss some otherwise valid values.
  2. That’s easily said and done when we have a big window between our thresholds, but what if our we have to divide a range of 0-50 in 3 sections, and our value fluctuates +/- 10 points? Moving the threshold is not as easy.

Another thing we can do is gather multiple values and then calculate their average, or the value that occurs most often. This helps minimize or completely remove the effects of spikes in our data, but it results in more delay, since we have to get a number of measurements before making a decision. However, it is an easy and well-know technique when fast response is not critical, and it can be used in addition to the technique i will show bellow, for even more accuracy.

So, what do I do when i have fluctuating variables with threshold that can be too close to each other? Well, i set a number of fixed values instead of thresholds (you can think of them as thresholds, but I’m not sure that’s the right term), and i measure the distance of my input in regards to each of my fixed points. The point closer to my value wins. Let’s take a look at the code:
uint8_t getNumOfRels(void)
{
int value = analogRead(relayCheckPin);
int relNum = 0;
int distance[5];
int thresholds[] = {0, 342, 512, 614, 683, 732 };
for(int i = 0; i< 6; i++)
thresholds[i] < value? distance[i] = value - thresholds[i] : distance[i] = thresholds[i] - value;

for(int i = 1; i< 6; i++)
if(distance[i] < distance[i-1]) relNum = i;

return relNum;
}

There are better ways to do it, but I’m picking this way strictly for educational purposes. This is Arduino code (taken from a sketch were I use an analog value to check how many relays are connected to my Arduino), so it’s really easy to understand. First of all, we use analogRead() to get an analog value, which ranges from 0 to 1023, but it can fluctuate a bit and therein lies our problem. We set 5 points of reference. Those are our theoretical valid points, and we calculate the distance of our analog value to each one of them. Then we compare the distances and we find which is the lowest one. This is our valid point. Our value could be off by a wide margin for a number of reasons, but we will always find the closest point of reference. To be certain of my results, I repeat this process 3-5 times and get the most prominent value. I’m proud to say this method has never failed me.

4 Responses to “Checking fluctuating variables using thresholds, the smart way.”

  1. Dimitrios LeventeasNo Gravatar said:

    Jun 03, 12 at 11:48 am

    Initially, intended as a comment here. A slightly different approach to the problem using Python.

    http://dimle.wordpress.com/2012/06/03/how-to-avoid-flunctuations-around-a-threshold/

  2. Efstathios ChatzikyriakidisNo Gravatar said:

    Jun 05, 12 at 10:52 am

    Μπορείς να βρεις εδώ μια υλοποίηση του μέσου όρου πόυ είχα κάνει πριν κάποια χρόνια:

    https://gitorious.org/control-device-on-off-through-relay-light-sensor/control-device-on-off-through-relay-light-sensor/blobs/master/development/control_device_on_off_through_relay_light_sensor/control_device_on_off_through_relay_light_sensor.ino

  3. Georgitzikis VasilisNo Gravatar said:

    Jun 05, 12 at 4:05 pm

    Κλασσική και σταθερή υλοποίηση μέσου όρου. nice.

    εγώ γενικά αποφεύγω τα delay() γιατί δουλεύω με xbee που στέλνουν και δέχονται δεκάδες πακέτα το δευτερόλεπτο, και το να κανεις delay() ακόμα και 100ms είναι εκτός συζήτησης.

  4. One day at a time said:

    Aug 23, 12 at 4:25 pm

    [...] read the interesting post Checking fluctuating variables using thresholds, the smart way from tzikis. Unfortunately, for some reason I can not post a comment [...]


Leave a Reply


Tzikis is using WP-Gravatar