adccmds: Add support for min/max temperature check filtering
Extend the ADC out of range check so that it is possible to sample multiple times before going into a shutdown state. This reduces the chance that measurement noise will cause an error. In an actual over temperature (or under temperature event) it is expected that the sensor will consistently report the problem, so extra checks for an additional second or two should not substantially increase risk. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
5b3444c060
commit
0dbfa915de
|
@ -8,6 +8,7 @@ import logging, bisect
|
|||
SAMPLE_TIME = 0.001
|
||||
SAMPLE_COUNT = 8
|
||||
REPORT_TIME = 0.300
|
||||
RANGE_CHECK_COUNT = 4
|
||||
|
||||
# Linear style conversion chips calibrated with two temp measurements
|
||||
class Linear:
|
||||
|
@ -50,7 +51,8 @@ class Linear:
|
|||
def setup_minmax(self, min_temp, max_temp):
|
||||
adc_range = [self.calc_adc(min_temp), self.calc_adc(max_temp)]
|
||||
self.mcu_adc.setup_minmax(SAMPLE_TIME, SAMPLE_COUNT,
|
||||
minval=min(adc_range), maxval=max(adc_range))
|
||||
minval=min(adc_range), maxval=max(adc_range),
|
||||
range_check_count=RANGE_CHECK_COUNT)
|
||||
def setup_callback(self, temperature_callback):
|
||||
self.temperature_callback = temperature_callback
|
||||
def get_report_time_delta(self):
|
||||
|
|
|
@ -9,6 +9,7 @@ KELVIN_TO_CELCIUS = -273.15
|
|||
SAMPLE_TIME = 0.001
|
||||
SAMPLE_COUNT = 8
|
||||
REPORT_TIME = 0.300
|
||||
RANGE_CHECK_COUNT = 4
|
||||
|
||||
# Analog voltage to temperature converter for thermistors
|
||||
class Thermistor:
|
||||
|
@ -59,7 +60,8 @@ class Thermistor:
|
|||
def setup_minmax(self, min_temp, max_temp):
|
||||
adc_range = [self.calc_adc(min_temp), self.calc_adc(max_temp)]
|
||||
self.mcu_adc.setup_minmax(SAMPLE_TIME, SAMPLE_COUNT,
|
||||
minval=min(adc_range), maxval=max(adc_range))
|
||||
minval=min(adc_range), maxval=max(adc_range),
|
||||
range_check_count=RANGE_CHECK_COUNT)
|
||||
def setup_callback(self, temperature_callback):
|
||||
self.temperature_callback = temperature_callback
|
||||
def get_report_time_delta(self):
|
||||
|
|
|
@ -350,17 +350,19 @@ class MCU_adc:
|
|||
self._pin = pin_params['pin']
|
||||
self._min_sample = self._max_sample = 0.
|
||||
self._sample_time = self._report_time = 0.
|
||||
self._sample_count = 0
|
||||
self._sample_count = self._range_check_count = 0
|
||||
self._report_clock = 0
|
||||
self._oid = self._callback = None
|
||||
self._inv_max_adc = 0.
|
||||
def get_mcu(self):
|
||||
return self._mcu
|
||||
def setup_minmax(self, sample_time, sample_count, minval=0., maxval=1.):
|
||||
def setup_minmax(self, sample_time, sample_count,
|
||||
minval=0., maxval=1., range_check_count=0):
|
||||
self._sample_time = sample_time
|
||||
self._sample_count = sample_count
|
||||
self._min_sample = minval
|
||||
self._max_sample = maxval
|
||||
self._range_check_count = range_check_count
|
||||
def setup_adc_callback(self, report_time, callback):
|
||||
self._report_time = report_time
|
||||
self._callback = callback
|
||||
|
@ -381,9 +383,10 @@ class MCU_adc:
|
|||
math.ceil(self._max_sample * max_adc))))
|
||||
self._mcu.add_config_cmd(
|
||||
"query_analog_in oid=%d clock=%d sample_ticks=%d sample_count=%d"
|
||||
" rest_ticks=%d min_value=%d max_value=%d" % (
|
||||
" rest_ticks=%d min_value=%d max_value=%d range_check_count=%d" % (
|
||||
self._oid, clock, sample_ticks, self._sample_count,
|
||||
self._report_clock, min_sample, max_sample), is_init=True)
|
||||
self._report_clock, min_sample, max_sample,
|
||||
self._range_check_count), is_init=True)
|
||||
self._mcu.register_msg(self._handle_analog_in_state, "analog_in_state"
|
||||
, self._oid)
|
||||
def _handle_analog_in_state(self, params):
|
||||
|
|
|
@ -15,6 +15,7 @@ struct analog_in {
|
|||
uint32_t rest_time, sample_time, next_begin_time;
|
||||
uint16_t value, min_value, max_value;
|
||||
struct gpio_adc pin;
|
||||
uint8_t invalid_count, range_check_count;
|
||||
uint8_t state, sample_count;
|
||||
};
|
||||
|
||||
|
@ -42,8 +43,15 @@ analog_in_event(struct timer *timer)
|
|||
a->timer.waketime += a->sample_time;
|
||||
return SF_RESCHEDULE;
|
||||
}
|
||||
if (a->value < a->min_value || a->value > a->max_value)
|
||||
try_shutdown("ADC out of range");
|
||||
if (likely(a->value >= a->min_value && a->value <= a->max_value)) {
|
||||
a->invalid_count = 0;
|
||||
} else {
|
||||
a->invalid_count++;
|
||||
if (a->invalid_count >= a->range_check_count) {
|
||||
try_shutdown("ADC out of range");
|
||||
a->invalid_count = 0;
|
||||
}
|
||||
}
|
||||
sched_wake_task(&analog_wake);
|
||||
a->next_begin_time += a->rest_time;
|
||||
a->timer.waketime = a->next_begin_time;
|
||||
|
@ -75,13 +83,14 @@ command_query_analog_in(uint32_t *args)
|
|||
a->rest_time = args[4];
|
||||
a->min_value = args[5];
|
||||
a->max_value = args[6];
|
||||
a->range_check_count = args[7];
|
||||
if (! a->sample_count)
|
||||
return;
|
||||
sched_add_timer(&a->timer);
|
||||
}
|
||||
DECL_COMMAND(command_query_analog_in,
|
||||
"query_analog_in oid=%c clock=%u sample_ticks=%u sample_count=%c"
|
||||
" rest_ticks=%u min_value=%hu max_value=%hu");
|
||||
" rest_ticks=%u min_value=%hu max_value=%hu range_check_count=%c");
|
||||
|
||||
void
|
||||
analog_in_task(void)
|
||||
|
|
Loading…
Reference in New Issue