Точный омметр для измерения термисторов

Тема в разделе "Arduino & Shields", создана пользователем Nutya, 9 июн 2020.

  1. Nutya

    Nutya Нуб

    Для измерения термисторов решил сделать омметр, но не устраивает точность измерений. Измерять нужно от 1кОм до 60 кОм, одновременно от 12 до 30 термисторов . Делитель поставил на 70,9 кОм.( делитель стоит между А0-GND для 1 мультиплексора и А1-GND для 2 мультиплексора)
    Для увеличения точности думаю или вводить поправочные коэффициенты, вычесленные эмперическим путем, либо попробовать собрать схему с мостом Уинстона, но с ним уменя как раз проблема - никак не могу сообразить как это сделать на основе ардуино.

    Схема прилагаю:

    [​IMG]
    [​IMG]
    Код (C++):
    #define EN 3
    #define S0 4
    #define S1 5
    #define S2 6
    #define S3 7
    #define SIG1 A0
    #define SIG2 A1
    #define R1 70900
    #define U_THERMISTOR    5000    //Напряжение подаваемое на термистор в мВольтах
    void setup()
    {
      Serial.begin(9600);

      pinMode(S0, OUTPUT);
      pinMode(S1, OUTPUT);
      pinMode(S2, OUTPUT);
      pinMode(S3, OUTPUT);

      digitalWrite(S0, LOW);
      digitalWrite(S1, LOW);
      digitalWrite(S2, LOW);
      digitalWrite(S3, LOW);

      pinMode(EN, OUTPUT);
      digitalWrite(EN, LOW);

      delay(1000); //Ждем переходные процессы в схеме
    }

    int ADCMux;

    void loop()
    {
      //Loop through and read all 16 values
      //Reports back Value at channel 6 is: 346
      for (int j = 0; j < 2; j ++)
      {
        Serial.print("Mux: ");
        Serial.print(j + 1);
        for (int i = 0; i < 16; i ++)
        {
          Serial.print(" ch");
          Serial.print(i);
          Serial.print(": ");
          ADCMux = readMux(j + 1, i);
          Serial.print(" [v1: ");
          Serial.print(ConvertADCToVoltage(ADCMux));
          //Serial.print(ADCMux);
          Serial.print(" r2: ");
          Serial.print(CalculateThermistor(ConvertADCToVoltage(ADCMux)));
          Serial.print("]");
        }
        Serial.println();
      }
      Serial.println();
      delay(2000);
    }

    /**
       Функция выбора мультиплексора и канала в нём
       @param  mux_n   Номер мультиплексора 1-2
       @param  channel Канал 0-15
       @return         Значение АЦП, -1 - ошибка выбора мультиплексора
    */

    int readMux(int mux_n, int channel)
    {
      int adc = 0;
      if ((mux_n <= 0) || (mux_n >= 3)) return -1;

      int controlPin[] = {S0, S1, S2, S3};

      int muxChannel[16][4] =
      {
        {0, 0, 0, 0}, //channel 0
        {1, 0, 0, 0}, //channel 1
        {0, 1, 0, 0}, //channel 2
        {1, 1, 0, 0}, //channel 3
        {0, 0, 1, 0}, //channel 4
        {1, 0, 1, 0}, //channel 5
        {0, 1, 1, 0}, //channel 6
        {1, 1, 1, 0}, //channel 7
        {0, 0, 0, 1}, //channel 8
        {1, 0, 0, 1}, //channel 9
        {0, 1, 0, 1}, //channel 10
        {1, 1, 0, 1}, //channel 11
        {0, 0, 1, 1}, //channel 12
        {1, 0, 1, 1}, //channel 13
        {0, 1, 1, 1}, //channel 14
        {1, 1, 1, 1} //channel 15
      };

      //loop through the 4 sig
      for (int i = 0; i < 4; i ++)
      {
        digitalWrite(controlPin[i], muxChannel[channel][i]);
      }
      delay(200);
      //return the value
      for (int i = 0; i < 16; i++)
          adc += analogRead(mux_n == 1 ? SIG1 : SIG2);
        return adc / 16;

      //return analogRead(mux_n == 1 ? SIG1 : SIG2);
    }

    /**
       Конвертируем показания АЦП в напряжение, в мВольтах
       @param  adc показания АЦП
       @return     напряжение, в мВольтах
    */

    uint16_t ConvertADCToVoltage(uint16_t adc)
    {
      return (adc * 4.8828125); //adc * (5000mV / 1024)
    }

    /**
       Находим значение термистора, в Ом
       @param  v1 напряжение на делителе
       @return    сопротивление термистора, в Ом
    */

    uint32_t CalculateThermistor(uint16_t v1)
    {
      return ((U_THERMISTOR * R1) / v1) - R1;
    }
     

    Вложения:

    • RY9q5gRGaSg.jpg
      RY9q5gRGaSg.jpg
      Размер файла:
      279,2 КБ
      Просмотров:
      226
    Последнее редактирование: 9 июн 2020
  2. Un_ka

    Un_ka Гуру

    Картинка не отображается.
    Между gnd и A0,A1 какого номинала резисторы 70,9кОм?
     
  3. Nutya

    Nutya Нуб

    засунул как вложение
     
  4. parovoZZ

    parovoZZ Гуру

    Такие штуки делают на основе RC измерителя. Но нужен очень стабильный опорник и конденсатор с нулевым ТКЕ.
     
  5. Nutya

    Nutya Нуб

    да
     
  6. Daniil

    Daniil Гуру

    Начните с конца. Какая точность вам нужна? Пересчитайте по схемам в напряжение, а далее нужно думать что получится
     
  7. Airbus

    Airbus Радиохулиган Модератор

    Бред какой то.Точное измерение постоянно меняющегося сопротивления.
     
  8. так весы работают, как бы.
    можно и АЦП оттуда позаимствовать.
     
  9. Airbus

    Airbus Радиохулиган Модератор

    Звер не так. Если бы так то постоянно меняли свои точные показания. В весах какраз точность загрублена. А тут ты взял его в руки—сопротивление поплыло. Открыл форточку— поплыло. Это если точно. Если грубо— можно омметром.
     
  10. Daniil

    Daniil Гуру

    вот как раз с определения точности и надо скакать, что я и предложил)
     
  11. b707

    b707 Гуру

    ТС на ардуино.ру пишет, что измерение проводится в термостате с точностью 0.03 градуса (если я правильно понял)
    Но вообще он какой-то мутный (ТС а не термостат :) - не ясно, понимает ли он то, что делает...
     
  12. Airbus

    Airbus Радиохулиган Модератор

    Опять же встает вопрос—насколько точен сам термистор?И вопрос 2— калибровка точки отсчета( ноля например или+100 С). Сам по себе термистор— аналоговый прибор. Поэтому я и удивился.
     
  13. а как? тензорезистор подключен к ацп.
     
  14. parovoZZ

    parovoZZ Гуру

    Точнее, чем вся эта ваша измерительная кухня.

    каждый с ума сходит по своему.
     
  15. Airbus

    Airbus Радиохулиган Модератор

    У меня на кухне Бош.А у Вас?:)
     
  16. Tatinek

    Tatinek Нуб

    Вам целочисленная арифметика портит всю точность.
    Код (C++):
    return (adc * 4.8828125)
    Это на самом деле работает так:
    Код (C++):
    return (adc * 4)
    Поменяйте тип ConvertADCToVoltage() на float или double.