Resolving a logic issue with Arduino user input

78 Views Asked by At

I'm working on an Arduino program that reads data from an anemometer and if the wind is above a certain threshold, it activates a relay. The threshold can be set in two ways:

1) The user can use two buttons to increase or decrease the threshold

2) If a certain button is held for 2 seconds, the threshold will sync with the current wind speed.

My problem is this: the increase and decrease buttons change the threshold value by +/- 0.5 km/h. But the wind speed is read with 0.1 km/h precision. So what can sometimes happen is if the current wind speed is, say, 12.2 km/h, and the sync button is held, the threshold now becomes 12.2 km/h. No problem yet...

But then if the user presses one of the increase/decrease buttons, the threshold still changes by +/- 0.5 km/h, meaning the values will increase like 12.2, 12.7, 13.2, 13.7, etc.

What I would like to have happen is for the increase/decrease buttons to put the threshold value to the nearest 0.5 multiple. So if the sync button was used, and the threshold was set to 12.2, pressing the increase button would change to 12.5, and then continue in steps of 0.5 from there.

I can think of a few ways to fix this issue, but none of them are very elegant. I want to use the simplest solution possible.

Note: I'm not including any of my code because this is more of a logic/pseudocode question. Also, this is my first forum post, so let me know if I need to change anything in my post!

EDIT: Pseudo, by request.

if increase button pressed

  threshold+=0.5

if decrease button pressed

  threshold-=0.5

if sync button held

  threshold = current wind speed
2

There are 2 best solutions below

0
On

Sophisticated C++ solution for Arduino (grin)

#include <math.h>

// button == 1 increase, button == 0 decrease
void adjust(float& level, char button) {
  float floorVal2=floor(level*2); // level*2 is equiv to level/0.5
  if(fabs(floorVal2-2*level)<1e-5 ) { 
    // they aren't close enough to consider them equal
    level=
        button
      ? (floorVal2+1)/2 // this is equiv to ceil(level/0.5)*0.5
      : floorVal2/2 // this is floor(level/0.5)*0.5
    ;
  }
  else {
    level += (button ? 0.5 -0.5)
  }
}

void read(float& level) {
  level=MySensor::getCurrentValue();
}
0
On
Handle_key_press_down(key, &threshold) {
   min_step = 0.5
   Hysteresis = min_step*0.6 // Avoid threshold that is exactly same as the current speed
   New_threshold = round_to_nearest(threshold, min_step)
   If (key == up) {
     New_thresh = Threshold + min_step
   Else if (key == down) {
     New_thresh = Threshold - min_step
   Else if (key == sync) {
      Wait_for_release
      If release_time >= 2.0s
        New_thresh = round_to_nearest(Get_current() + Hysteresis, min_step)
      Else
        ignore
  Endif
  // Insure, no matter what, threshold is within design limits.
  If (New_thresh > threshold_max) New_thresh = threshold_max
  If (New_thresh < threshold_min) New_thresh = threshold_min
  return New_thresh
}