[решено] Проблема с экспериментом 15 (Комнатный термометр) в Матрёшка Z. Формула для термистора.

Тема в разделе "Arduino & Shields", создана пользователем altex, 27 июл 2014.

  1. altex

    altex Гик

    Проблема с экспериментом 15 (Комнатный термометр)
    http://wiki.amperka.ru/конспект-arduino:комнатный-термометр

    Показывает не ту температуру, которая есть на самом деле.
    В помещении температура 24-25 градусов, а программа показывает 14-15 градусов.
    Видимо проблема в формуле.

    В даташите (http://files.amperka.ru/datasheets/B57164.pdf) написано, что при 25 градусах должно быть 10 КОм сопротивление.
    При 20 градусах должно быть на четверть выше. Значит напряжение было бы тоже примерно на четверть выше.

    Видно, что напряжение составляет 2.44, что характерно для 10 КОм (+-), однако по формуле из конспекта получается температура 15 градусов.

    Код программы:

    Код (Text):
    #include <math.h>

    #define FIRST_LED_PIN 2
    #define LED_COUNT 10

    void setup() {
      for (int i = 0; i < LED_COUNT; ++i) {
        pinMode(i + FIRST_LED_PIN, OUTPUT);
      }
      Serial.begin(9600);
    }

    void loop() {
      float voltage = analogRead(A0) * 5.0 / 1023.0;

      Serial.println("-----------------------");
      Serial.print("Voltage=");
      Serial.print(voltage);
      Serial.println("");

      float temperature = -14.46 * log(
        (10000.0 * voltage)
        / (5.0 - voltage)
        / 27074.0
      );

      Serial.print("Temperature=");
      Serial.print(temperature);
      Serial.println("");

      for (int i = 0; i < LED_COUNT; ++i) {
        boolean enableSegment = (temperature >= 21 + i);
        digitalWrite(9 - i + FIRST_LED_PIN, enableSegment);
      }

      delay(1000);
    }
     
    Лог:

    Код (Text):
    -----------------------
    Voltage=2.44
    Temperature=15.05
    -----------------------
    Voltage=2.45
    Temperature=15.00
     
     
  2. altex

    altex Гик

    Замерил вольтметром
    Если в логе написано, что напряжение 2.49, но вольтметром я вижу 2.38 (вольтметром)

    P.S. Причём напряжение между "+5" и землёй - 4.78 (замерял вольтметром)
    Это к сути дела не относится.
     
    Последнее редактирование: 27 июл 2014
  3. altex

    altex Гик

    По логике вещей (из даташита) сопротивление для комнатных температур должны укладываться в следующие значения (напряжение расчитано для питания 5В и резистором 10К )

    15.0 | 1.5858 | R = 15.9 КОм | U = 3.07 В
    20.0 | 1.2507 | R = 12.5 КОм | U = 2.78 В
    25.0 | 1.0000 | R = 10 КОм | U = 2.5 В
    30.0 | 0.7964 | R = 7.96 КОм | U = 2.22 В

    Тоесть 2.45 должно примерно означать температуру между 25 и 30 и ближе к 25.

    Вобщем у меня сомнения в правильности формулы
    Код (Text):
      float temperature = -14.46 * log(
        (10000.0 * voltage)
        / (5.0 - voltage)
        / 27074.0
      );
     
    Кто знает правильную формулу? :)
     
  4. geher

    geher Гуру

    analogRead выдает напряжение не относительно пяти, а относительно опорного, которое равно напряжению питания, если не подано на соответствующий контакт другое опорное и не задан нужный параметр вызовом analogReference(). По-моему так.
    Если реальное напряжение питания 4.78, то, в зависимости от ситуации варианты могут быть разными.
    Если питание от USB, то либо USB на ПК слабоват, что не может обеспечить должное питание, либо кабель плоховат, что такое серьезное падение напряжения.
    Если питание от внешнего БП на Vin или на разъем питания, то либо напряжение на входе питания маловато (меньше 7), либо регулятор на ардуине чудит.
     
  5. altex

    altex Гик

    Это интересно, спасибо. Действительно, при питании от кроны напряжение на пине "+5 В" относительно земли равняется 5.02 В.

    А можете помочь с основным вопросом?
     
    Последнее редактирование: 28 июл 2014
  6. ALev

    ALev Гик

    Добрый день!

    Да, действительно похоже, что в нашей формуле имеется ошибка. Проверяем. Как найдём правильный ответ, отпишемся.
     
  7. ALev

    ALev Гик

    Разобрались. Формула оказалась другой. Вот правильная реализация:

    Код (Text):
    float volt = analogRead(A0)*5.0/1023.0;
    float r1 = volt / 2.5; // R_t/R_25C
    unsigned int B = 4300; // Параметр конкретного типа термистора (из datasheet)

    float temp = 1./( 1./(B)*log(r1)+1./298. ) - 273;
    Спасибо за то, что помогли сделать наши примеры лучше!
     
    eigenein и altex нравится это.
  8. ALev

    ALev Гик

    Вот прямая формула:
    CodeCogsEqn.gif
    А вот обратная:
    CodeCogsEqn1.gif

    T - температура
    R_T - сопротивление при температуре T
    R_25C - сопротивление при температуре 25°С
    β - коэффициент, имеющий размерность К (Кельвин). В документации на наш сенсор значится β=4300. На практике может отличаться на ±5%.
     
    eigenein и altex нравится это.
  9. lerik2703

    lerik2703 Гик

    как -то не работает формула или что-то не дописано!пока отбросим датчик а просто будем изменять напряжение на порту !получается диапазон от 251(0.v) -11.34(5.v)
     
  10. ALev

    ALev Гик

    Вот этот скетч у меня выводит правильную температуру. Только не поменяйте местами термистор и резистор, сделайте, как в примере. Если всё равно не заработает, обращайтесь.

    Код (Text):
    #include <math.h>

    void setup()
    {
      Serial.begin(19200);
    }

    void loop()
    {
      float volt = analogRead(A0)*5.0/1023.0;
      float r1 = volt / 2.5; // R_t/R_25C
      unsigned int B = 4300; // Параметр конкретного типа термистора (из datasheet)
     
      Serial.println(1./( 1./(B)*log(r1)+1./298. )-273);
     
      delay(100);
    }
     
    eigenein нравится это.
  11. lerik2703

    lerik2703 Гик

    а вы весь температурный диапазон проверяли , в холодильник засовывали :)
    это то понятно ,если поменять показания будут обратные если холодно он покажет горячо и наоборот!
    я не про датчик вообще ,а про формулу и проверяю её не на ардуинке а на компьютерной программе!
     
  12. ALev

    ALev Гик

    Тогда объяснитесь пожалуйста, о каких вольтах вы говорите. В формуле о вольтах нет ни слова, поэтому я не в полне понял, что у вас с чем не срослось.
     
  13. lerik2703

    lerik2703 Гик

    вы про это 251(0.v) -11.34(5.v)
     
  14. altex

    altex Гик


    Спасибо большое за оперативный ответ, новые правильные формулы и подробные объяснения к ним. Приятно, что такой высокий уровень поддержки.
    Теперь всё работает корректно (почти, об этом ниже).
     
    Последнее редактирование: 29 июл 2014
  15. altex

    altex Гик

    Я думаю, что формула расчёта сопротивления не совсем точная

    Код (Text):
    float r1 = volt / 2.5; // R_t/R_25C
    Здесь же делитель напряжения, а значит R будет расчитываться так:

    Код (Text):
    float r1 = volt * 10000.0 / (5.0 - volt); // Rconst=10KOm, Vin=5v
    И соответственно формула температуры чуть-чуть изменится

    Код (Text):
      float temperature = 1./( 1./(B)*log(r1/10000.0)+1./298. ) - 273;
    Итого финальный вариант формулы в скетче у меня получился такой:

    Код (Text):
      float voltage = analogRead(A0) * Vin / 1023.0;
      float r1 = voltage * 10000.0 / (Vin - voltage);
      unsigned int B = 4300; // Параметр конкретного типа термистора (из datasheet)

      float temperature = 1./( 1./(B)*log(r1/10000.0)+1./298. ) - 273; // 10KOm - R_25
     
    Например, если схватиться пальцами за термистор, то с предыдущей формулой он показывал около 30 градусов, а с новой формулой около 34.5, что более точно.
    Когда же я подносил плату к кондиционеру, который 16 градусный ветер гонит, то с предыдущей формулой было 22, с новой меньше 20 (не замерял, просто все светодиоды по одному перестали гореть). Так что думаю, что это более точная формула.
     
    Последнее редактирование: 29 июл 2014
    lerik2703 нравится это.
  16. lerik2703

    lerik2703 Гик

    вот это уже правильно, возвращается весь диапазон температур!в целом погрешность (без учета допуска постоянного резистора) от 0 до 100 составляет 0,5-1 градус (о,5 ближе к 25) ,при долее низких и высоких порядка 2-5 градусов!
    для комнатного термометра подойдет ,ну а если требуется точность во всем диапазоне температур рассчитывать лучше по значению ADC!
     
    Последнее редактирование: 29 июл 2014
  17. lerik2703

    lerik2703 Гик

    кстати это
    float r1 = voltage * 10000.0 / (Vin - voltage);
    float temperature = 1./( 1./(B)*log(r1/10000.0)+1./298. ) - 273; // 10KOm - R_25
    можно и убрать!
     
  18. ALev

    ALev Гик

    altex, да, поторопился. Ваши правки совершенно верны. Замечание lerik2703 тоже, кстати.
     
  19. lerik2703

    lerik2703 Гик

    тогда ждем обновления статей :rolleyes:
     
  20. altex

    altex Гик

    Лучше так не делать. Значения случайно совпали, но это разные переменные в формулах.

    10kOm в первой строчке - это постоянный резистор
    10kOm во второй строчке - это сопротивление термистора при 25 градусах
    Если поменяется термистор или постоянный резистор, то температура будет рассчитываться некорректно, а по формуле будет складываться впечатление, что температура вообще не зависит от выбираемых номиналов сопротивлений.

    Очень прошу авторов методичек в примерах такие сокращения не делать. Так как это была одна из причин, по которым я не смог решить проблему самостоятельно и задал вопрос на форуме - у меня не было исходных формул (и было не понятно, что означают числа на подобии "-14.46" в готовой формуле).