ESR-метр

Тема в разделе "Arduino & Shields", создана пользователем Salk, 8 июл 2016.

  1. Salk

    Salk Гик

    Прошу подсказки, как реализован программный принцип измерения ESR конденсаторов в данной схеме.
    [​IMG]
    Измерительные резисторы только у себя поставил на 500 Ом.
    Я не пытаюсь 1 в 1 повторить схему, а взять принцип измерения ESR конденсаторов из этой схемы.

    Пробовал вычислять напряжение на "-" ножке конденсатора в момент подачи положительного импульса к "+" конденсатора. За счет кратковременного КЗ на конденсаторе, была идея вычислить разницу (падение напряжения) между подаваемым напряжением на "+" конденсатора и "-". А дальше по закону Ома, банально, рассчитать ESR (эквивалентное сопротивление): R = Uпад / I заряда конд.
    Но получается белиберда, уж больно большие значения сопротивлений ESR у меня получаются.
    Порядка единиц - десятков Ом, а ведь должно раз в 10 меньше.
    Код (C++):
    float Voltag1; // напряжение на А0
    float Voltag2; // напряжение на А1

    byte a;
    float ESR;

    void setup()
    {
      Serial.begin(9600);
      pinMode(8, OUTPUT);
      pinMode(10, OUTPUT);
      digitalWrite(10, LOW);
      // analogReference(INTERNAL);
    }

    void loop()
    {
      if (a != 1)
      {
        Conder();
        a = 1;
      }
    }

    void Conder()
    {
      // подаем на ножку "+" конденсатора импульс
      digitalWrite(8, HIGH);
      // delay(1);
      Voltag1 = ((float)analogRead(A0) / 1024) * 5.09; // находим напряжение на первом аналговом порте
      Voltag2 = ((float)analogRead(A1) / 1024) * 5.09; // находим напряжение на втором аналговом порте
      ESR = (Voltag1 - Voltag2) / (Voltag2 / 500); // R = U пад / I; I = U / R
      Serial.print(analogRead(A1));
      Serial.print(" - ");
      Serial.print(ESR);
      Serial.println(" Omh");

      a = 1; // ставим флаг, чтобы цикл не повторился
      delay(100);
      // разряжаем конденсатор
      digitalWrite(8, LOW);
    }
    Конденсатор на 10 мкФ (ESR - 4.97 Omh) и 1000 мкФ (ESR - 12.97 Omh)
    upload_2016-7-8_21-17-39.png
    Боюсь мОм по данному методу измерить не получится, не хватит разрядности АЦП (ОУ не хочется городить), тогда как реализован метод измерения ESR в данной схеме "тестера РЭ"?
    Что-то из теории припоминаю ещё про сдвиг фаз тока относительно напряжения, но ума не приложу, как реализовать это в коде. Может я вообще не в ту степь побрел?
     
  2. Salk

    Salk Гик

    Окей, такой метод явно не подходит для atmega, т.к. разрешение ацп не позволяет уловить незначительные изменения, да и одновременно считать напряжения с двух выводов конденсатора не удастся.
    Окей, нашел вот что: метод Маркуса, кто хочет пораскинуть мозгами?
    Описание работы схемы Маркуса в полном русском переводе. Описание метода измерения ESR (страница 58), я воспользовался первым.
    Делал, все как по учебнику, но что-то не то вовсе получается, не могу понять, либо ошибка в переводе на русский язык, либо фатальная ошибка в коде.
    Привожу код, он не сложный, но с одной формулой возникли непонятки (Uesr), или я не так понял написанное в описании к схеме.
    Код (C++):
    float Voltag1; // напряжение на А0
    float Voltag2; // напряжение на А1

    byte a;
    float Resr; // ESR
    float Uhp; // U со "+" стороны конденсатора с током, 128 раз повторений
    float Ulp; // U со "-" стороны конденсатора с током, 128 раз повторений
    float Uc; // U со "+" стороны конденсатора без тока, 128 раз повторений
    float Udiff; // Разница Uhp - Ulp
    float Uesr; // Разница Udiff - Uc, падение напряжения на внутреннем сопротивлении конденсатора при зарядке
    float Uhpsumm; // сумма 128 значений
    float Ulpsumm; // сумма 128 значений
    float Ucsumm; // сумма 128 значений

    void setup()
    {
      Serial.begin(9600);
      pinMode(A0, INPUT); // вход
      pinMode(A1, INPUT); // вход
      pinMode(8, OUTPUT);
    // pinMode(9, OUTPUT);
      pinMode(10, OUTPUT);
    // pinMode(11, OUTPUT);
      digitalWrite(8, LOW); // контакты к которым подсоединен конденсатор
      digitalWrite(10, LOW); // контакты к которым подсоединен конденсатор
    //analogReference(INTERNAL);
    }

    void loop()
    {
    // 1 раз
    if (a != 1)
    {
        Esr();
        a = 1;
    }
    }

    // Resr = (Uesr * 10 * Rport) / Ulp
    void Esr()
    {
    // Переводим на опорное 1.1 В
      analogReference(INTERNAL);
      pinMode(8, OUTPUT);
      pinMode(10, OUTPUT);

    // находим Uhp = U со "+" стороны конденсатора с током, 128 раз повторений
    for (int i = 0; i < 128; i++)
    {
       // начинаем заряд конденсатора
        digitalWrite(8, HIGH); // "+"
        digitalWrite(10, LOW); // "-"
        delayMicroseconds(900); // с частотой менее 600 Гц
        digitalWrite(8, LOW); // разряжаем конденсатор
        delayMicroseconds(900);
       // находим Uhp
        Uhp = (1.1 / 1024.0) * analogRead(A0);
        Uhpsumm = Uhpsumm + Uhp; // сумма
        Serial.print("Uhp: ");
        Serial.print(Uhp);
        Serial.print("V");
        Serial.print(" Summ: ");
        Serial.print(Uhpsumm);
        Serial.println("V");
    }
    // условно ждем 1с
      delay(1000);
      Serial.println(" ");

    // находим Ulp = U со "-" стороны конденсатора с током, 128 раз повторений
    for (int i = 0; i < 128; i++)
    {
       // начинаем заряд конденсатора c измененной полярностью
        digitalWrite(8, LOW); // "+"
        digitalWrite(10, HIGH); // "-"
        delayMicroseconds(900); // с частотой менее 600 Гц
        digitalWrite(10, LOW); // "-"
        delayMicroseconds(900); // с частотой менее 600 Гц
       // // находим Ulp
        Ulp = (1.1 / 1024.0) * analogRead(A1);
        Ulpsumm = Ulpsumm + Ulp; // сумма
        Serial.print("Ulp: ");
        Serial.print(Ulp);
        Serial.print("V");
        Serial.print(" Summ: ");
        Serial.print(Ulpsumm);
        Serial.println("V");
    }
    // условно ждем 1с
      delay(1000);
      Serial.println(" ");

    // находим Uc = U со "+" стороны конденсатора без тока, 128 раз повторений
    for (int i = 0; i < 128; i++)
    {
       // начинаем заряд конденсатора
        digitalWrite(8, HIGH); // "+"
        digitalWrite(10, LOW); // "-"
        delayMicroseconds(900); // с частотой менее 600 Гц
       // снимаем ток с конденсатора, переводя в высокоимпедансное состояние
        pinMode(8, INPUT);
       // Считываем показания Uc без тока
        Uc = (1.1 / 1024.0) * analogRead(A0); // ток без приложенного напряжения выше, чем с ним
        Ucsumm = Ucsumm + Uc; // сумма
       // разряжаем конденсатор
        pinMode(8, OUTPUT);
        digitalWrite(8, LOW);
        delayMicroseconds(900);
        Serial.print("Uc: ");
        Serial.print(Uc);
        Serial.print("V");
        Serial.print(" Summ: ");
        Serial.print(Ucsumm);
        Serial.println("V");
    }
    // условно ждем 1с
      delay(1000);
      Serial.println(" ");

    // Находим Udiff
      Udiff = Uhpsumm - Ulpsumm;
      Serial.print("Udiff: ");
      Serial.print(Udiff);
      Serial.println("V");

    // условно ждем 1с
      delay(1000);
      Serial.println(" ");

    // находим Uesr - *с ним не очень ясно*, должно быть (Udiff - Uc), но так получается отрицательное число
      Uesr = Uc - Udiff;
      Serial.print("Uesr: ");
      Serial.print(Uesr);
      Serial.println("V");

    // условно ждем 1с
      delay(1000);
      Serial.println(" ");

    // Вычисляем сопротивление ESR согласно формуле, получается *полная ахинея*
    // "резистор порта", он же измерительный, я поставил 500 Ом
      Resr = (Uesr * 10 * 500) / Ulpsumm;
      Serial.print("Resr: ");
      Serial.print(Resr);
      Serial.println(" Omh");
    }
    И вот, что в мониторе:
    [​IMG][​IMG][​IMG]

    Где допустил ошибку? Может я не правильно истолковал эти слова на странице 58:
    При тесте конденсатора я, пытался, сымитировать меандр счастотой около 600 Гц (delayMicroseconds(900));, и совсем запутался.

    P.s. Изображения открываются правой кнопкой мыши "в новой вкладке", скриншоты на фото хостинге.
     
  3. AlexU

    AlexU Гуру

    Так у Вас вряд ли получиться. Первое что бросается в глаза -- Вы подаёте импульс, а потом производите измерение. Я не знаю всех тонкостей в реализации "Тестера ЭРЭ", но там используется аппаратный ШИМ для генерации меандра и измерения производятся одновременно с меандром. Почему бы Вам так же не воспользоваться аппаратным ШИМ. Только его надо будет настроить под нужную частоту. И желательно не трогать ШИМ на 5 и 6 ногах Arduino (порты PD5, PD6), нулевой таймер (работает примерно на частоте 1 кГц) используется для подсчета времени и от него зависит работа таких функций как 'delay()', 'millis()'.
    Второе, если правильно понял, в "Тестере ЭРЭ" производятся замеры напряжений на обоих контактах конденсатора и разница этих напряжений даёт падение напряжения на конденсаторе, которое обуславливается пресловутым ESR.
    Так же надо замерить сопротивление "щупов", к которым подключается конденсатор, при коротком замыкании и использовать в качестве поправки перед выдачей результатов.
     
  4. Salk

    Salk Гик

    Спасибо за ответ, хоть кто-то отписался :)
    Но я не думаю, что там используется аппаратный ШИМ, поскольку в схеме пины для измерения используются с D8 по D13, при этом там всего 3 с поддержкой ШИМ (9,10,11), таким образом необходимо будет прикладывать тестовый конденсатор только к измерительным клемам "ТР1 и ТР2", т.к. ТР3 вовсе не имеется поддержку ШИМ, согласно схеме. А это не удобно.
    Я не совсем понял, что Вы имели ввиду под
    Разве это не то: ?
    Код (C++):
    // начинаем заряд конденсатора
        digitalWrite(8, HIGH); // "+"
        digitalWrite(10, LOW); // "-"
        delayMicroseconds(900); // с частотой менее 600 Гц
        digitalWrite(8, LOW); // разряжаем конденсатор
        delayMicroseconds(900);
    // находим Uhp
        Uhp =(1.1/1024.0)* analogRead(A0);
    Если сделать измерение сразу после выставления логической единицы, то конденсатор не успеет зарядится и на 0.1 В, он выводит фактическое напряжение равное "0".
    Если делать так:
    Код (C++):
    // начинаем заряд конденсатора
        digitalWrite(8, HIGH); // "+"
    // находим Uhp
        Uhp =(1.1/1024.0)* analogRead(A0);
        digitalWrite(10, LOW); // "-"
        delayMicroseconds(900); // с частотой менее 600 Гц
        digitalWrite(8, LOW); // разряжаем конденсатор
        delayMicroseconds(900);
    Я полагаю ошибка вовсе в переводе, или я что-то недопонимаю. Согласно конспекту - описание работы схемы измерение ESR первым методом:
    Т.е. делаем суммирование всех этих напряжений 128 раз, суммы получаются большими, при этом при нахождении Udiff, используется разница Uhp и Ulp, а вот Uc остается большой суммой из 128 сложений.
    Так, как по формуле Uesr = Udiff - Uc у нас может получится положительное число? Зачем тогда нам вообще эта сумма Uc?
    Тут нужно быть нехилым теоретиком-математиком, чтобы все это понимать, но при переводе описания этого метода, явно допущены ошибки :)
     
  5. Salk

    Salk Гик

    А Вы наверно имели ввиду такой подход:?
    Код (C++):
    // начинаем заряд конденсатора
        digitalWrite(8, HIGH); // "+"
        digitalWrite(10, LOW); // "-"
        delayMicroseconds(900); // с частотой менее 600 Гц
    // находим Uhp
        Uhp =(1.1/1024.0)* analogRead(A0);
        digitalWrite(8, LOW); // разряжаем конденсатор
        delayMicroseconds(900);
    Стоит попробовать, спасибо.
     
  6. AlexU

    AlexU Гуру

    Вполне вероятно, что ошибаюсь, т.к. досконально не изучал исходники, а только пробежался глазами "по диагонали" -- в коде есть инициализация ШИМ'а, но может для других целей.
    Вы пробовали посмотреть на исходники этого тестера? Может сможете понять что и как он делает для измерения ESR. (Есть желание в будущем собрать такой тестер, поэтому исходники буду внимательно изучать, но пока занят другим проектом).
    Не совсем. Честно говоря плохо представляю как должен выглядеть финальный код. Но если я правильно понимаю суть ESR, то в момент заряда конденсатора (пока через него течёт ток) падение напряжения на конденсаторе выше, чем напряжение заряда конденсатора (если через него не течёт ток). Это повышенное падение напряжения возникает за счёт паразитного последовательного сопротивления -- ESR. Вот условная картинка переходного процесса заряда конденсатора:
    ESR.jpg
    Т.е. для вычисления ESR нужно узнать разницу напряжений Uesr (падение при заряде и заряженного конденсатора) и ток заряда конденсатора. Грубо говоря нужно начать заряд конденсатора, замерить падение напряжения на конденсаторе и ток через него, потом остановить зарядку и замерить напряжение заряда конденсатора. При чём сделать это нужно очень быстро, иначе значения "поплывут". И желательно замеры производить в начале заряда, т.к. разница Uesr уменьшается по мере заряда конденсатора и соответственно погрешность растёт. Таких замеров в процессе заряда можно сделать несколько и выдать "средний" результат.
    Так вот по поводу "сделать очень быстро" -- с функциями digitalRead, digitalWrite, analogRead и т.п. Вы быстроты не добъётесь, значения будут очень сильно плавать. Поэтому нужно работать напрямую с регистрами -- так хоть погрешность снизите, хотя полностью погрешность не одолеете. При этом учитывать нужно несколько факторов: первое -- АЦП имеет погрешность, второе АЦП -- один, соответственно измерить можете что-то одно (ток или одно из напряжений), а пока контроллер будет переключаться для измерения другой величины и сам АЦП производить преобразование, пройдёт время, в течении которого конденсатор зарядиться ещё больше (хоть и на малые доли напряжения), что соответственно увеличит погрешность.
    Вот как-то так....
     
  7. krepton85

    krepton85 Нуб

    Ну судя по этому видео

    ESR нужно измерять так:
    1. находим по формуле Rc = 1/2пfC сопротивление конденсатора (здесь нужно знать частоту переменного тока).
    2. далее нужно каким то чудом измерить падение напряжения (переменного или постоянного не понятно, но ESR только для полярных конденсаторов, скорей всего переменного т.к. сопротивление конденсатора рассчитывается для переменного тока) на конденсаторе и зная падение напряжение и ток, определить общее последовательное сопротивление конденсатора Rc+ ESR , а далее отнять от этой суммы сопротивление конденсатора и получим как раз ESR.
    Но как измерить падение переменного напряжения на конденсаторе если он подключен между 2-мя пинами микроконтроллера?