Как включить Vref в расчет температуры термистора?

схема

Это код, который я использую для получения температуры:

#define COEFF_A 0.8662984364E-03
#define COEFF_B 2.780704551E-04
#define COEFF_C -0.9395108479E-07

float VRT, Temp;
float Vref = 2.52;


void setup() {
  Serial.begin(9600);
  analogReference(EXTERNAL);
}

void loop() {
  long Resistance;
  VRT = analogRead(A3);
  Resistance = 10000 / ((1023.0 / VRT) - 1);
  Temp = log(Resistance);
  Temp = 1 / (COEFF_A + (COEFF_B * Temp) + (COEFF_C * pow(Temp, 3)));
  Temp += -273.15;
  Serial.println(Temp);
  delay(500);
}

Я знаю, что вычисление должно быть следующим: V = Vref × VRT ÷ 1023, но я не знаю, как внедрить его в этот код, буду признателен за любую помощь.


Обновить

После ответа Эдгара Боне отредактированный код:

#define COEFF_A 0.8662984364E-03
#define COEFF_B 2.780704551E-04
#define COEFF_C -0.9395108479E-07

float VRT, Temp, VR;


void setup() {
  Serial.begin(9600);
  analogReference(EXTERNAL);
}

void loop() {
  long Resistance;
  VRT = analogRead(A3);
  VR = 2.52 * VRT / 1024;
  Resistance = 10000 * VR / (2.52 - VR);
  Temp = log(Resistance);
  Temp = 1 / (COEFF_A + (COEFF_B * Temp) + (COEFF_C * pow(Temp, 3)));
  Temp += -273.15;
  Serial.println(Temp);
  delay(500);
}

Но показания температуры на 2 градуса по Цельсию меньше, чем должны быть, когда я удаляю analogReference(EXTERNAL); он показывает нормальные/правильные показания температуры.

, 👍0


2 ответа


Лучший ответ:

2

Формула для получения аналогового напряжения из показаний АЦП:

    V = Vref × чтение ÷ 1024

(да, это 1024, а не 1023). Формула для определения сопротивления термистора от измеренного напряжения составляет:

    R = Rref × V ÷ (Vref – V)

где Rref — подтягивающий резистор 10 кОм. Вы можете комбинировать эти две формулы для того, чтобы получить сопротивление непосредственно из АЦП чтение:

    R = Rref × чтение ÷ (1024 – чтение)

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


Обновление 1: после редактирования OP у нас теперь есть совершенно другой вопрос. Теперь возникает вопрос: как получилось, что показания зависят от используется опорное напряжение, тогда как теоретически они не должны использоваться.

Скорее всего, ответ заключается в калибровке АЦП. Если высокая точность требование, правильная формула для измеренного напряжения:

    V = Vref × (показание + Eвыкл.) ÷ (1024 + Eусиление)

где Eвыкл и Eусиление — ошибка смещения, а ошибка усиления соответственно. Эти ошибки не известны априори, и они обычно пренебрегают, когда требования к точности невелики. таблица данных только дает ограничения на то, насколько большими могут быть эти ошибки. фактические значения зависят от конкретного микроконтроллера и могут несколько зависит от опорного напряжения. Единственное решение, чтобы избавиться от этих ошибки заключается в калибровке собственного АЦП. См. ответ Arduino ADC для примера того, как это можно сделать.


Обновление 2: если бы мне пришлось программировать это в Arduino, я бы предпочел максимально упростить расчеты перед кодированием:

  • не не вычислять измеренное аналоговое напряжение или сопротивление, т.к. они не нужны
  • вместо этого вычислить отношение R/Rref непосредственно из аналогового чтение
  • перепишите калибровочный полином как функцию log(R/Rref) вместо log(R) (что фактически означает log(R/(1 Ω)))
  • оптимизировать вычисление полинома с помощью метод Хорнера.

Благодаря этим оптимизациям мы получаем:

// Коэффициенты полиномиальной аппроксимации log(R/Rref) -> 1/Т.
const float c0 = 3.3540165e-3;
const float c1 = 2.5416075e-4;
const float c2 = -2.5959644e-6;
const float c3 = -9.3951087e-8;

// Преобразование показаний АЦП в температуру в градусах. С.
static float temperature(int reading)
{
    float R_ratio = reading / (1024.0 - reading);  // = R / Rref
    float x = log(R_ratio);
    float inverse_T = c0 + x*(c1 + x*(c2 + x*c3));
    return 1/inverse_T - 273.15;
}

void loop()
{
    int reading = analogRead(A3);
    Serial.println(temperature(reading));
    deay(500);
}
,

поэтому в этом примере должно быть так: «Сопротивление = 2,52 * ВРТ / (1024 - ВРТ);», правильно?, @ElectronSurf

Нет. Ваше эталонное сопротивление составляет 10 кОм, а не 2,52 Ом., @Edgar Bonet

но показания неверны, "Сопротивление = 10000 * ВРТ / (1024 - ВРТ);" я что-то пропустил? вроде на 2С меньше..., @ElectronSurf

Я не понимаю вашего последнего комментария. Пожалуйста, отредактируйте исходный вопрос, если чего-то не хватает., @Edgar Bonet

когда я использую предложенную вами формулу «Сопротивление = 10000 * ВРТ / (1024 - ВРТ); температура на 2 градуса по Цельсию меньше, чем должна быть., @ElectronSurf

если я не удалю analogReference(EXTERNAL);, это означает, что он не игнорирует «отмену» Vref!, @ElectronSurf

Обновите свой вопрос., @Edgar Bonet

Отредактировал вопрос., @ElectronSurf

Статья, на которую вы ссылаетесь, - это кусок золота, спасибо., @ElectronSurf


0

Примечание. Я сформулировал этот ответ на ваш предыдущий удаленный вопрос.

Увеличивается или уменьшается напряжение при повышении температуры, зависит от вашей схемы: если вы используете ntc с R1 в качестве понижающего напряжения, напряжение будет увеличиваться при повышении температуры. Если R1 является подтягивающим, напряжение соответственно упадет.

Что касается вашего расчета: я настоятельно рекомендую вместо этого использовать справочную таблицу. Это сложные расчеты, и при разрешении ардуино вам подойдет LUT с примерно 64 записями. Существуют инструменты, которые генерируют LUT для данной настройки NTC (лично мне нравится этот инструмент ).

,

эээ, мне так плохо, что я удалил этот вопрос, пока ты отвечал на него! извини..., @ElectronSurf

код, который я разместил в своем вопросе, выполняет все расчеты, мне не нужно его повторять, мне просто нужно добавить Vref в расчет, и я не знаю, как это сделать... между прочим, это выпадающее меню., @ElectronSurf