Here I asked about how to add an hysteresis on ADC readings. The answer received was very good and it worked out of the box.
Still I'm having troubles trying to generalize the resample
function in order to map the input values to a different range of output values, where the lower rail is not zero.
If the lower rail was zero, it would be enough to change the shifts with a multiplication/division for 1024 / max
. But I cannot understand how to handle the lower rail when min > 0
.
My attempt:
int Menu::resample(int adc, int *value, byte min, byte max)
{
// sanity checks omitted: min < max and max < 128
double m = 1015.0 / (max - min); // 1015 = 1023 - 8 (1 LSB of low-res output)
// otherwise it reaches 126 even if max = 127
int q = min << 3;
int lowerTest = (q + *value * m) - ADC_HYSTERESIS;
int higherTest = (q + (*value + 1) * m) + ADC_HYSTERESIS;
int lowerOutput = min + (adc + ADC_HYSTERESIS) / m;
int higherOutput = min + (adc - ADC_HYSTERESIS) / m;
if (adc < lowerTest) *value = lowerOutput;
else if (adc >= higherTest) *value = higherOutput;
if (*value > max) *value = max;
if (*value < min) *value = min;
return *value;
}
There is something wrong in my math, since the comparison always falls under the first if
(i.e. *value = lowerOutput
).
May you help me to fix this code so I can have an hysteresis on any scaled output?
Note: instead of using a static variable for value as in the answer, I use a struct
:
slider.value = resample(adc, &slider.lastValue, slider.min, slider.max);
where:
typedef struct
{
int value;
int lastValue;
int min;
int max;
} slider_t;
slider_t slider;