Перейти к содержанию
    

Малоресурсный алгоритм измерения температуры

прошу помощи в плане общего алгоритма... лучшей темы для своего вопроса не нашел...

 

требуется измерять температуру тела человека, при этом процесс измерения от наблюдателя скрыт - никаких цифр никуда не выводится, т.е. человек не может принять решение, что измерение завершено. требуется алгоритм определения того, что температура датчика уже достигла окончательного значения, т.е. процесс измерения завершен. проблем две: алгоритм должен требовать минимум ресурсов и давать верный результат за минимальное время. из дополнительных условий: измерение температуры - АЦП 15 бит (оверсемплинг), измерение 1 раз в секунду.

 

что сделано сейчас и что не удовлетворяет (псевдо-Си-код)

t2 = 0;

do{

t1 = t2;

pause_1s();

t2 = get_temperature();

} while (t1 != t2);

 

это дает отличный результат при измерении температуры воды (большая теплоемкость, контакт с датчиком идеальный, быстро его нагревает) - за 15 секунд получается верный результат. для тела человека как правило цикл завершается за 0,3-0,6°С до реальной температуры, что не устраивает. кроме того, процесс длится не менее 30 секунд...

 

какие будут советы?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

прошу помощи в плане общего алгоритма... лучшей темы для своего вопроса не нашел...

....

это дает отличный результат при измерении температуры воды (большая теплоемкость, контакт с датчиком идеальный, быстро его нагревает) - за 15 секунд получается верный результат. для тела человека как правило цикл завершается за 0,3-0,6°С до реальной температуры, что не устраивает. кроме того, процесс длится не менее 30 секунд...

 

какие будут советы?

Варианта два.

1) Надо подождать, пока температура застабилизируется. Например, пока не получите пять одинаковых показаний датчика.

2) Надо оценить скорость нарастания температуры и по форме этой кривой попробовать экстраполировать эту кривую

на пару минут вперед. Но тут уже могут быть грабли в виде разной теплопроводности кожи людей в зависимости от...

Так что первый пункт надежнее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

что сделано сейчас и что не удовлетворяет (псевдо-Си-код)

t2 = 0;

do{

t1 = t2;

pause_1s();

t2 = get_temperature();

} while (t1 != t2);

 

это дает отличный результат при измерении температуры воды (большая теплоемкость, контакт с датчиком идеальный, быстро его нагревает) - за 15 секунд получается верный результат. для тела человека как правило цикл завершается за 0,3-0,6°С до реальной температуры, что не устраивает. кроме того, процесс длится не менее 30 секунд...

 

какие будут советы?

 

 

Можно, например, сделать Ваш алгоритм робастным, если t1 и t2 считать не изолироваными измерениями, а результатом фильтрации измеренных величин. Причем, лучше взять не скользящее среднее, а медианную фильтрацию

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

спасибо.

у меня была фильтрация скользящим средним по 16 точкам - результат был вроде более удовлетворительный, но очень уж долгим... в некоторых случаях и по 3 минуты шел процесс... кроме того, из-за скудности ресурсов от фильтрации пришлось отказаться :( я понимаю, что надо ждать N одинаковых показаний, и чем больше N, тем вернее будет найдено решение задачи... но есть вопрос, например, такого плана: обнаружив, что не все N равны между собой, как поступить лучше? отбросить первое отличающееся значение и продолжать ждать равного остальным? сдвинуть массив предыдущих значений по типу скользящего среднего и продолжать "заталкивать" туда новые значения, добиваясь, чтобы все стали одинаковыми? обнулить все и начать снова? проблема в том, что младщий бит, а то и 2, результата АЦП "дрожит"... как бы не попасть в бесконечный цикл...

 

у меня есть термометр OMRON. так вот эта штука измеряет либо до стабилизации показаний, либо 2 минуты. в любом случае то, что к концу 120 секунд будет на индикаторе - то и считается реальной температурой. алгоритм вроде нормальный, но долгий... и все равно какой-то негарантированный - чуть расслабился, перестал прижимать термометр подмышкой - получил нормальную температуру во время гриппа :(

 

я уже близок к тому, что просто 1-2 бита отбросить при анализе на равенство... в принципе, должно хватить...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

прошу помощи в плане общего алгоритма... лучшей темы для своего вопроса не нашел...

 

требуется измерять температуру тела человека, при этом процесс измерения от наблюдателя скрыт

какие будут советы?

Если теплопроводность в процессе измерения не меняется, а именно: площадь контакта и сила прижима не меняются, тогда можно пользоваться экстраполяцией. Но "малоресурсно" ли получится, зависит от Ваших ресурсов.

Вариант. Если к датчику добавить нагреватель, который предварительно нагревает датчик до... пусть будет 36 градусов, то можно ускорить, если датчик относительно массивный. Нагревателем может служить и сам датчик.

Есть еще вариант - измеряется температура. Пусть она растет. Тогда датчик немного нагревается дозированным током. Опять смотрим за дрейфом (скоростью изменения) температуры при малом токе.... Это вариант для термосопротивления с (полу)мостовой схемой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

что сделано сейчас и что не удовлетворяет (псевдо-Си-код)

t2 = 0;

do{

t1 = t2;

pause_1s();

t2 = get_temperature();

} while (t1 != t2);

 

Попробуйте так (код написан исходя из 16-битной разрядности int)

// Допустимые колебания показаний,
// вы говорите, что дрожат младшие 2 бита, накинем еще один, чтобы избежать ложного перезапуска осреднения
#define ERROR 8
#define AVERAGE_SHIFT 4
// Количество показаний для осреднения,
// whatever you like чтобы получить больше точность, в данном случае 16
#define AVERAGE_COUNT (1<<AVERAGE_SHIFT)

#define ABS(a) ((a)>=0 ? (a) : -(a))

int t1;
int t2;
long int average = 0; // если разрядности хватит для суммирования температур из области
                               //допустимых значений, то long может и не нужен
int count = 0

t2 = get_temperature();
do
{
  t1 = t2;
  if (!count)
    pause_long(); // достаточно долго, чтобы датчик успел нагреться/остыть на величину больше ERROR
  else
    pause_1s(); // при осреднении интервалы короче (может, можно и чаще чем раз в секунду?)

  t2 = get_temperature();
  if (ABS(t2-t1)<ERROR)
  {
    // если температура устаканилась, начинаем считать среднее
    average+=t2;
    count++;
  }
  else
  {
    // если температура не устаканилась, или опять начала меняться, сбрасываем среднее и опять ждём
    average=0;
    count=0;
  }
} while (count<AVERAGE_COUNT);

average>>=AVERAGE_SHIFT; // результат

Надеюсь, четыре int в стеке - это не слишком большие ресурсы.

Изменено пользователем il--ya

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

проблема в том, что младщий бит, а то и 2, результата АЦП "дрожит"... как бы не попасть в бесконечный цикл...

Чтобы этого не было можно закончить тогда, когда измерения перестали быть больше максимального получившегося значения в течении N измерений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если взять за основу электрический эквивалент, то:

1. тело человека - источник эдс постоянного тока.

2. датчик - ёмкость конечной величины (конденсатор)

3. теплопроводность от тела к датчику - резистивная проводимость (величина обратная резистивному сопротивлению)

4. окружающая среда - резистивный ток утечки ёмкости (датчика). Пренебрегаем этой утечкой.

Что мы имеем?

При возникновении контакта ёмкость (датчик) начинает заряжаться с постоянной времени RC и т.д.

В нашем же случае при использовании такой модели, мы получаем график роста показаний термометра:

Тд = Тд.н + (Тт - Тд.н)*(1 - exp (- k * t)), где

Тд - текущая температура датчика,

Тд.н. - начальная температура датчика

k - конструктивная постоянная времени (зависит от физ.свойств поверхности тела и датчика)

t - время в секундах.

Можно было бы сделав 2 замера, вычтя начальное значение датчика, расчитать через натуральный логарифм постоянную k и вычислить величину Тт, к которой стремится значение Тд. Но для этого термометр надо включить так, чтобы нагрев датчика не произошёл. Иначе мы получим смещение Тд.н. из-за инерционности датчика. Как правило, термометр вертят в руках, касаясь датчика, да и в вычислении логарифма, а потом и экспоненты - приятного мало в рамках малоресурсного алгоритма.

Предлагаю сделать 3 замера через равные интервалы времени, но на начальном участке нагрева, например в 5, 15 и 25 секунд и воспользоваться свойством экспоненты сохранять отношение текущего приращения к прошлому.

Иначе говоря, отношение (Tд(25) - Тд(15)) / (Тд(15) - Тд(5)) будет справедливо ко всем последующим приращениям, взятым с таким же интервалом времени.

Ну и вот - запускаете итерацию с накоплением результата до тех пор, пока расчётное приращение не станет ниже допустимой погрешности.

P.S. если дрожит младший бит - делайте подряд 8-16 измерений (сравнительно быстро, конечно) и вычисляйте по ним среднее для текущего времени.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

прошу помощи в плане общего алгоритма... лучшей темы для своего вопроса не нашел...

 

требуется измерять температуру тела человека, при этом процесс измерения от наблюдателя скрыт - никаких цифр никуда не выводится, т.е. человек не может принять решение, что измерение завершено

 

Что-то вроде упрощенного фильтра Калмана. Рекурсивное усреднение (это займет минимум памяти) со скользящим весом (это даст максимально быстрое нахождение результата). Например, так.

 

Номер слева указывает порядковый номер измерения, res - 32-битное целое:

 

1: res = (meas << 16);

2,3: res = res - (res >> 1) + (meas << 15); // вес очередного измерения meas равен 1/2

4...7: res = res - (res >> 2) + (meas << 14); // вес измерения равен 1/4

8...15: res = res - (res >> 3) + (meas << 13); // вес измерения равен 1/8

... и т.д., однако далее некого предела вес уменьшать нельзя

 

Процедура считается завершенной, если в течении каждого из нескольких последних измерений изменение результата меньше, чем некий доверительный интервал.

 

Процедуру можно усовершенствовать, если переход на следующий шаг (с уменьшенным весом) тоже будет происходить в результате проверки, обнаруживающей, что результат стал изменяться сравнительно мало. Конечно, при этом доверительный интервал тоже должен уменьшаться на каждом шаге.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...