О терморезисторе замолвите слово...

Доброго.
Нашёл у себя в детальках NTC терморезисторы EPCOS, и захотел оценить, насколько точно можно с их помощью измерять температуру. Я не буду склонять или разубеждать использовать терморезисторы, это каждый для себя пусть решает сам. Кому любопытно — смотрите под катом.NTC full range
В моём случае это были B57621. Если посмотреть документацию, то характеристик мы не найдём, но есть отсылка к "No. of R/T characteristic" в зависимости от номинала, где можно увидеть, что сопротивление от температуры зависит весьма нелинейно. Тут стоит вспомнить, что типовое применение термисторов — это включение как делитель напряжения совместно с обычным резистором. А вот какое соотношение резисторов взять? Я набросал в Excell LibreOffice Calc табличку, построил по ней диаграмму и попробовал поменять отношения резисторов (за единицу берётся значение NTC при 25).
У меня были с номиналом 10кОм, соответственно — для них всё и оценивалось. Изображение выше — это и есть полученные графики для температур от -55 до 125 °С. Ошибка здесь — это ошибка расчёта при линейной аппроксимации между крайними точками диапазона.
Подбирая отношение постоянного резистора к номинальному сопротивлению термистора по минимальной ошибке получим для указанного диапазона минимум на величине 0,7. Для 10 кОм ближайший из ряда Е24 это 7,2 кОм и ожидаемая максимальная ошибка 11,4%.

Для более узкого температурного диапазона, например — 0..70 °С, можно добиться меньшей ошибки. Минимальный разбег будет при добавочном резисторе в 0,534 от номинального, а если ограничиться стандартным рядом — 5,1 кОм при максимальной ошибке 1,57%, что уже вполне применимо в ряде разработок.


PS: Всё это, разумеется, идеализированно, и понятно, что у терморезисторов будет как разброс характеристик, например — разброс номинальной величины, так и могут добавиться погрешности измерения. Да и контроллеры сейчас позволяют не только хранить всю таблицу характеристики, но и считать какую угодно аппроксимацию, а не только линейную. Для меня же польза потраченного времени была в том, что для разных диапазонов в делитель следует включать резисторы с разным соотношением к номинальному терморезистора для получения минимальной ошибки при линейной аппроксимации.
  • 0
  • 06 мая 2015, 08:58
  • Hoksmur
  • 1
Файлы в топике: NTC.zip

Комментарии (50)

RSS свернуть / развернуть
Извини, не понял. Ты под линейной аппроксимацией что понимаешь? Просто прямую линию, которая строится по точкам -55 — +125 градусов? Или берёшь табличку из своей второй pdf и делаешь ахапку линий, которые привязаны к точкам с шагом в 5 градусов?
Вроде бы в реальной жизни основная проблема в точности АЦП, которой не хватает, чтобы охватить весь диапазон -55 — +125. И его хорошо бы порезать на части. Ты это имел в виду, когда говорил «что для разных диапазонов в делитель следует включать резисторы с разным соотношением к номинальному терморезистора для получения минимальной ошибки при линейной аппроксимации.»?
+1
Линейная по крайним точкам диапазона; соответственно -55..125 и 0..70 градусов.
0
А сколько бит у твоего АЦП, который измеряет напряжение на делителе??
0
Просто прямую линию по крайним точкам диапазона, а не «охапку». «Охапка» как раз подразумевалась под «хранить всю таблицу характеристики».
Про АЦП не совсем понял. Проблема может быть в нелинейности самого АЦП, или разрешающей способности: напряжение будет меняться от 0,065 при 125°С до 0,986 при -55°С. Но в диапазоне входных значений — вряд ли, кмк.
Оценим: K(120°С)-K(125°С)=0.056407-0.050196=0.006211. На 1 градус ~0.006211/5=0.0012422 от напряжения делителя. При 10 бит ADC один бит будет 1/1024=0.000976. То есть на градус 1,27 бита. Плюс-минус лапоть.
Или вы про что-то другое?
0
Да, именно это я и имею в виду.
Вот только при температуре в -55 градусов на делителе образуется напряжение меньшее 1 МЗР АЦП.
А при -50 — около 1МЗР. То есть, будет около одного бита на 5 градусов.
В результате 10 битного АЦП не хватит, чтобы измерять отрицательные температуры.
(Честно говоря, я брал свои цифры, тоже от epcos, который на 100К, думаю для твоих будет то же самое).
0
Хм… а у меня хватает. В вашем случае характеристика 4901.

Файл
0
Судя по всему, у тебя термистор в нижнем плече делителя, а у меня в верхнем. Плюс, у меня АЦП работает в диапазоне от 0 до 5В (и делитель тоже от 5В запитан), у тебя — от 0 до 1В.
Попробовал пересчитать для нижнего плеча:
2015-05-06 10-48-50 Microsoft Excel - Без имени 1.xls  [Режим совместимости].png

Я исходил из следующих «входных» данных:
Характеристика моего термистора — 2005.
Сопротивление при 25 градусах — 100К.
На картинке выше он в нижнем плече (как и у тебя).
В верхнем плече делителя — резистор в 15К.
Напряжения я считал вот так:
U = Rt / (15K + Rt)

Питать его, видимо, придётся от источника в 1В ;)

Между -50 и -55 получается 0.5 деления АЦП.

Файлик твой я посмотрел, в нём не хватает строчки для U(-50).

Можешь сказать характеристику своего термистора?
0
Не-не-не. У меня характеристика 1010. Мы по разному подошли к выбору резистора. R у меня «в разах» от номинального NTC во всех расчётах. И да — U = Rt/(R + Rt).
Питать делитель от Vref, я исходил из этого. Даже если это не самое стабильное напряжение питания, то это ничего не меняет, поскольку делитель делит со своим коэффициентом любое напряжение. У вас R существенно отличается от Rt, думаю — в этом причина.
Давайте дальше. Какой у вас диапазон температур требуется и какое разрешение, какая погрешность допустима? Отсюда и будем плясать.
Посмотрите как считается у меня в файлах — может и у меня где ошибки, тоже ведь может быть.
Можно же не всю таблицу хранить, а разбить на, допустим, 4 участка. Форма кривой погрешности («S») подсказывает, что неплохо и на полном диапазоне улучшит точность.
0
Забил в файл твои цифры (термистор 10К, характеристика 1010).
Для пары температур -50 — -55 получается разница напряжений 69мВ. А один разряд АЦП — 97мВ.
И, кажется, когда ты прикидывал чуть выше
K(120°С)-K(125°С)=0.056407-0.050196=0.006211
— ты посчитал это в Омах. А чуть ниже брал 1/1024 — это уже в вольтах. Ежели я чего не путаю!
0
На счёт омы-вольты верно, ошибка; поторопился, когда отвечал.
Про ваш случай: из таблиц для характеристики 2005 берём коэффициенты 120,22 при -55°С и 85,48 при -50°С. С резистором 15кОм коэффициенты передачи делителя (термистор в верхнем плече):
для -55°С — 15/(15+100*120,22)=0,0125
для -50°С — 15/(15+100*85,48)=0,0175


Предположим, что Vref АЦП и напряжение питания делителя — это напряжение питания 5в. Отсюда, для 10-битного АЦП:
V(lsb) = 5/1024 = 0.00488В
U(-55) = 5*0.0125 = 0.0625В
U(-50) = 5*0.0175 = 0.0875В


В отсчётах АЦП:
ADC(-55) = U(-55)/V(lsb) = 0.0625В/0.00488В = 12.8 = 0x0C
ADC(-50) = U(-50)/V(lsb) = 0.0875В/0.00488В = 17.9 = 0x11


Ищите ошибку. ;) И резистор в делитель бы побольше взяли всё же.

PS: Если Vref и питание делителя одно и то же напряжение — результат не будет меняться при изменении абсолютной величины этого напряжения.

С днём радио всех!
0
Блин, для нижнего плеча считал. *facepalm*
Но суть не меняется. Результаты конечные только будут 0x400-0x0C = 0x3F4 и 0x400-0x11=0x3EF
0
А-а-а-а!*facepalm* Вместо 0x400 надо брать 0x3FF
0
Не, все правильно — Vref на входе соответствует выходной код 0x400.
0
для -55°С — 15/(15+100*120,22)=0,0125
У тебя здесь ошибка на порядок.
Правильное значение: 0,00125.
+1
Эх, высыпаться лучше надо. И всё же:
При R = 100кОм: U(-55) = 5*( 100/(100+100*120.22) ) = 5*(100/12122) = 5*0.00825=0.0412В
Это 0.0412/0.00488 = 8.45 = 0x08.
Но вы потеряете в верхнем диапазоне чувствительность. Чем у вас обусловлен выбор резистора?
0
Проблема с резистором в том, что как его не выбирай, он не позволит использовать весь диапазон терморезистора, при 10-битном АЦП.
О том что речь идёт про весь диапазон я понял вот из этого твоего комментария:
we.easyelectronics.ru/Theory/o-termorezistore-zamolvite-slovo.html#comment155894

Просто на мой взгляд есть некоторое противоречие между:
1. ты говоришь, что используешь 10 бит АЦП;
2. ты пытаешься сделать линейную аппроксимацию по точкам -55 — +125 градусов.
0
Позволит. Весь. Вопрос — с каким разрешением и с какой ошибкой? И всё ещё до кучи завязано на второй резистор в делителе. Собственно, его выбор и побудил поделиться ходом мыслей со всеми.
Могу я вас попросить для вашего случая посчитать показания 10-битного АЦП на -55°С и +125°С? Используем в делителе R=75кОм. Если не лениво, конечно.
0
при постоянном резисторе 47кОм и 10кОм терморезисторе с коэфф чувствительности 3988 и 10-ти битным АЦП получаем 3 значения, указывающие на -55. Значения 987 — 989
0
Вот файлик.
Значение резистора можно поменять на какое угодно.
Собственно, его выбор и побудил поделиться ходом мыслей со всеми.
Да, спасибо, я понял.
Оценка точности ценна сама по себе без оглядки на АЦП :)
0
Порог ещё можно поймать, но разрешение меньше 1 бита на градус… Только по аппноту, подсказанному Mihail
0
У меня в предыдущем посте ссылка на файл есть. А ваш можно увидеть?
0
Файл
Сохранял из LibreOffice в формате excel, хз, откроется он, или нет.
0
я не понимаю одного. Ну да, разрядов АЦП не хватает точно измерить. А кто-нибудь здесь про шумы слышал? А про цифровые сглаживающие фильтры? По-моему их использование легко решит проблему недостачи разрядности. В некоторые АЦП шумы вводят намеренно как раз для этих целей, чтобы иметь на входе «дребезг» числа, а при вычислении среднего из всех этих чисел получать значение, по точности превышающее точность самого АЦП.
+1
Спасибо что напомнил. Пойду перечитаю AVR121: Enhancing ADC resolution by oversampling
0
Чуть ниже написал, как борюсь с этим. И всё-равно предпочитаю измерения делать Slope-ADC (компаратор и разряд емкости до опоры), ограниченном разрядностью таймера.
0
Что-то пошло не так ;)
yadi.sk/i/jPiOBK2NgTAF7
0
Сервер и ты в разных часовых поясах.
0
Если посмотреть документацию, то характеристик мы не найдём
Вот, например, здесь по характеристикам из даташита можно сгенерировать таблицу для определения температуры.
Необходимо как раз знать номер характеристики R/T и B параметры.

Да и вообще, искать надо тщательнее.
0
А вот здесь как раз таблицы этих характеристик.
0
То же, что и у меня открывается по «No. of R/T characteristic» :)
0
justmoose.ru/thermostat/thermostat.html
То же самое, только без JavaScript, и на 7 лет пораньше :))
0
oops, antonluba, я ответил не на тот коммент.
Это был мой ответ на твой первый комментарий.
0
Ставлю параллельно NTC постоянный резистор с номиналом, чуть бОльшим номинального сопротивления NTC при 25 градусах. Существенно «сужается» динамический диапазон.
0
по формуле, описаной в вышеупомянутой статье, пересчет получается довольно точный. Когда-то давно делал прогу на delphi для расчета таблицы.
0
0
0
а здесь собственно то, что может быть интересно из всей программы:
procedure TForm2.Button1Click(Sender: TObject);
var
  I,bb,n,m,x: Integer;
  R,Ku,Rt,T,B,Tn,Rn:Extended;
  S,SS:String;
begin
 R:=SpinEdit3.Value;
 Tn:=25+273.15;
 B:=SpinEdit1.Value;
 Rn:=SpinEdit2.Value;
 Memo1.Clear;
 if Radiobutton1.Checked then
  begin
   n:=256;
   m:=256;
   S:='.db $63';
   SS:='.db $';
   x:=2;
  end
 else
  begin
   n:=65536;
   m:=1024;
   S:='.dw $6300';
   SS:='.dw $';
   x:=4;
  end;
 for I := 1 to m-1 do
  begin
   Ku:=I/m;
   Rt:=Ku*R/(1-Ku);
   T:=Tn/((Ln(Rt/Rn)*Tn)/B+1)-273.15;
   bb:=round(T*n/256);
   if bb>(99*n/256) then bb:=99*n div 256;
   if bb<-99*n/256 then bb:=-99*n div 256;
   if bb<0 then
    bb:=n+bb;
   if (i mod 16)=0 then
    S:=SS+IntToHex(bb,x)
   else
    S:=S+', $'+IntToHex(bb,x);
   if (i mod 16)=15 then
    memo1.Lines.Add(S);
  end;
end;
+2
специально для этой темы заново переписал прогу на Qt
может кому полезно будет
+1
0
функция по сглаживанию и возврату значений температуры:
float Adc10ToTemp(unsigned short adc)
{
    static float ADC = 0;
    unsigned short Adc;
    if (adc > 1023) adc = 1023;
    ADC = (ADC * 99.0 + adc) * 0.01;
    Adc = ADC + 0.5;
    return (float)(TempTable[Adc]) / 256.0
}
0
вот так правильнее:
float Adc10ToTemp(unsigned short adc)
{
    static float Adc_Average = 0;
    unsigned short Adc_Int;
    float Adc_Frac;
    float Result;
    if (adc > 1023) adc = 1023;
    Adc_Average = (Adc_Average * 99.0 + adc) * 0.01;
    Adc_Int = floor(Adc_Average);
    Adc_Frac = Adc_Average - Adc_Int;
    if (Adc_Int = 1023)
        Result = (float)(TempTable[Adc_Int]) / 256.0;
    else
        Result = (((float)(TempTable[Adc_Int]) * Adc_Frac) + 
                  ((float)(TempTable[Adc_Int + 1]) * (1 - Adc_Frac)) / 256.0;
    return Result;
}
0
if (Adc_Int = 1023)
нужно исправить на
if (Adc_Int == 1023)
0
Пишите так:
if (1023 == Adc_Int)
Если пропустите один символ равенства, компилятор выдаст ошибку.
0
Если пропустите один символ равенства, компилятор выдаст ошибку.

Так не канонично :) нужно:

Ошибку выдаст компилятор, равенства символ один пропустите если. Условия Йоды
+2
Иногда удивляет, насколько много существует в мире вещей о которых даже не подозревал даже в той области, которую часто применяешь)
0
void Termo::on_pushButton_clicked()
{
    ui->plainTextEdit->clear();
    QString S;
    QString SS;
    if(ui->radioButton_8->isChecked())
        SS = "const char TempTable[256] = {";
    else
        SS = "const short TempTable[1024] = {";
    ui->plainTextEdit->appendPlainText(SS);

    double R = ui->R_Box->value();
    double Rn = ui->Rn_Box->value();
    double Tn = 25+273.15;
    double B = ui->B_Box->value();
    int n;
    int m;
    if(ui->radioButton_8->isChecked())
    {
        n = 1;
        m = 256;
    }
    else
    {
        n = 256;
        m = 1024;
    }
    for(int i = 0; i < m; i++)
    {
        double Ku;
        double T;
        if(ui->radioButton_Gnd->isChecked())
            Ku = (double)i / (double)m;
        else
            Ku = 1.0 -(double)i / (double)m;
        double Rt = Ku*R/(1-Ku);
        if(Rt == 0.0)
            T = 127.0;
        else
            T = Tn / ((log(Rt/Rn)*Tn)/B + 1) - 273.15;
        if(T > 127.0) T = 127.0;
        if(T < -127.0) T = -127.0;
        int bb = floor(T * n + 0.5);
        if (bb < 0)
            bb += (n << 8) - 1;
        S.setNum(bb,16);
        switch (i & 0x0F)
        {
        case 0:
            SS = "        0x" + S + ", ";
            break;
        case 15:
            if(i == m - 1)
                SS += "0x"+S +"];";
            else
                SS += "0x"+S +", ";
            ui->plainTextEdit->appendPlainText(SS);
            break;
        default:
            SS = SS + "0x"+S + ", ";

        }
    }
}
0
кстати, нашел отличную статью по теме
0
В этой статье Погребняк Дмитрий пляшет от обратного. Он генерирует в таблице значения АЦП, а порядковый номер в массиве — это собственно температура. После этого он ищет по таблице порядковый номер, которому бы соответствовало значение АЦП со значением ячейки. После — линейная интерполяция. У этого метода в отличии от моего есть преимущества и недостатки:
Преимущества: Меньший размер таблицы
Недостатки: Хромает точность у границ диапазона. Особенно если использовать усреднение по многократным выборкам; Сравнительно долгий анализ и поиск нужного значения
0
«Терморизостор» — я не въехал, в чём прикол?
0
Спасибо. Опечатка, поправил.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.