Делаю зарядное-разрядное для АКБ. Есть вопросы.

Тема в разделе "Arduino & Shields", создана пользователем iwizard7, 19 ноя 2016.

  1. iwizard7

    iwizard7 Нерд

    Доброго дня.
    Начинаю делать устройство на ардуино которое будет циклически включать либо зарядное устройство либо нагрузку в виде лампы 55W. Так сказать для тренировки АКБ. Собрал делитель напряжения из двух резисторов на 100кОм и на 10 кОм, все нормально показывает более менее. Но когда подключаю реле то показания начинают плавать и вообще показывать чушь, насколько я понимаю то проседает опорное напряжение на ардуине и потому так происходит. Подскажите как сделать правильно, чтобы напряжение определялось нормально и реле работало.Вот скетч
    Код (C++):
    /*
      Charger
    */


    int analogInput = 1;  // Пин (аналоговый) подключения делителя напряжения
    float vout = 0.0;
    float vin = 0.0;
    float R1 = 100000.0; // Значение резистора R1 (100K)
    float R2 = 10000.0;  // Значение резистора R2 (10K)
    int value = 0;
    void setup() {

      pinMode(7, OUTPUT); //Пин реле 1 - Заряда
      pinMode(8, OUTPUT); //Пин реле 2 - Разряда

      Serial.begin(9600);

      pinMode(analogInput, INPUT);

    }
    void loop() {
      // read the value at analog input
      value = analogRead(analogInput);
      vout = (value * 5.0) / 1024.0; // Выходное напряжение делителя до 5в
      vin = vout / (R2 / (R1 + R2));
      if (vin < 0.09) {
        vin = 0.0;
      }

      /*
        lcd.setCursor(0, 1);
        lcd.print("INPUT V= ");
        lcd.print(vin);
      */

      Serial.print(vin);
      Serial.println("  ");

      if (vin < 10.40) {      // Напряжение выключения разряда
        digitalWrite(7, HIGH);
        digitalWrite(8, LOW);
      }

      if (vin > 13.70) {      // Напряжение включения заряда
        digitalWrite(7, LOW);
        digitalWrite(8, HIGH);
      }
    }
    Модуль реле вот такой: [​IMG]
     
  2. MDV

    MDV Гик

    Для начала проверь алгоритм работы
    Сколько режимов работы ты заложил?
    Второе изучи тему заряда аккумуляторов, у каждого типа своя специфика, простое отключение от зарядника при достижении определенного напряжения тебе ничего не дас так как будет недозаряд акб.
    Теперь вернёмся к твоему вопросу
    Зачем вводить переменные если сопротивления в делителе у тебя константы и необходимый в расчетах коэффициент ты можешь посчитать на калькуляторе
    Второе уточни реле подключаешь вместе с акб и разрядной нагрузкой?
     
  3. iwizard7

    iwizard7 Нерд

    Вообще планируется два режима, либо идет зарядка акб либо разрядка через нагрузку.
    Заряжен или нет аккум до 100% считать этим устройством и не планируется, достаточно весьма приблизительно определять когда выключать зарядку и включать нагрузку, задача этого устройства делать циклы, для "тренировки". Дозаряжать до 100% буду нормальным зарядным устройством.
    Про переменные не совсем понял, зачем что то считать на калькуляторе если можно измерить сопротивления и записать в переменную.
    Реле будет два, на одно будет включать нагрузку (лампу). Через второе будет включаться зарядное устройство.Когда включено одно, другое конечно же будет выключено.
     
  4. rkit

    rkit Гуру

  5. iwizard7

    iwizard7 Нерд

  6. iwizard7

    iwizard7 Нерд

    Еще один момент который я пока не могу сообразить как организовать, при разрядке можно мерить напряжение постоянно и не париться, но при зарядке нужно на какое то время отключать заряд, измерять напряжение и опять включать зарядку если еще мало заряжен АКБ. Может подскажет кто как это организовать все в скетче? На данный момент скетч такой:
    Код (C++):
    /*
      Charger
    */

    //===================Библиотеки===================
    #include <LiquidCrystal_I2C.h>
    #include <Wire.h>
    LiquidCrystal_I2C lcd(0x20,16,2);  // Настройка параметров дисплея
    //===================Переменные===================
    int analogInput = 1;  // Пин (аналоговый) подключения делителя напряжения
    float vout = 0.0;
    float vin = 0.0;
    float R1 = 100000.0;  // Значение резистора R1 (100K)
    float R2 = 9910.0;  // Значение резистора R2 (10K)
    float UPV = 14.50;  // Порог заряда АКБ
    float DWV = 11.20;  // Порог разряда АКБ
    int value = 0;

    void setup() {

      lcd.init();
      lcd.backlight();

      pinMode(7, OUTPUT);  //Пин реле 1 - Заряда
      pinMode(8, OUTPUT);  //Пин реле 2 - Разряда
      pinMode(analogInput, INPUT);

      Serial.begin(9600);


    }
    void loop() {
      // Процедура чтения данных с аналогового порта
      value = analogRead(analogInput);
      vout = (value * 5.0) / 1024.0; // Выходное напряжение делителя до 5в
      vin = vout / (R2 / (R1 + R2));
      if (vin < 0.09) {
        vin = 0.0;

      }

      Serial.print("INPUT V= ");
      Serial.print(vin);
      Serial.println("  ");

      lcd.setCursor(1, 0);
      lcd.print("INPUT V= ");
      lcd.print(vin);

      lcd.setCursor(0, 1);
      lcd.print(UPV);

      lcd.setCursor(11, 1);
      lcd.print(DWV);

      if (vin < DWV) {     // Зарядка
        digitalWrite(7, HIGH);
        digitalWrite(8, LOW);

      }

      if (vin > UPV) {    // Разрядка
        digitalWrite(7, LOW);
        digitalWrite(8, HIGH);
      }

    }
     
     
  7. MDV

    MDV Гик

    Пару мыслей
    При запуске скетча задай состояние реле так как есть вероятность что при старте получишься работу зарядника на нагрузку
    Введи задержки между циклами лупа
    Измеряй среднее за несколько замеров
    Введи переменную (флаг) которая будет отражать статус процесса, с его помощью легко будет организовать отключение зарядника для измерения напряжения и в случае невыполнения нужного условия продолжать процесс зарядки
     
    iwizard7 нравится это.
  8. MDV

    MDV Гик

    По сопротивлениям
    Операции с плавающей точкой не всегда дают верный результат плюс к этому тормозят процес и съедают много памяти. При 20-30 строчек скетча это не проблема но ресурсы МК не безграничны. Измерить напряжение можно одной сточкой вписав соответствующий коэффициент который легко рассчитать один раз на калькуляторе и вписать в скетч, как пример R1+R2 в твоём случае 109910 Ом.
     
    iwizard7 нравится это.
  9. iwizard7

    iwizard7 Нерд

    Спасибо за советы и дельные идеи, буду реализовывать пока это
     
  10. Onkel

    Onkel Гуру

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

    iwizard7 Нерд

    Можно по подробней?
     
  12. Onkel

    Onkel Гуру

    https://www.arduino.cc/en/Reference/AnalogReference
    analogReference()
    Description
    Configures the reference voltage used for analog input (i.e. the value used as the top of the input range). The options are:

    • DEFAULT: the default analog reference of 5 volts (on 5V Arduino boards) or 3.3 volts (on 3.3V Arduino boards)
    • INTERNAL: an built-in reference, equal to 1.1 volts on the ATmega168 or ATmega328 and 2.56 volts on the ATmega8 (not available on the Arduino Mega)
    • INTERNAL1V1: a built-in 1.1V reference (Arduino Mega only)
    • INTERNAL2V56: a built-in 2.56V reference (Arduino Mega only)
    • EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference.
    Syntax
    analogReference(type)

    Parameters
    type: which type of reference to use (DEFAULT, INTERNAL, INTERNAL1V1, INTERNAL2V56, or EXTERNAL).

    Returns
    None.

    Note
    After changing the analog reference, the first few readings from analogRead() may not be accurate.

    Warning
    Don't use anything less than 0V or more than 5V for external reference voltage on the AREF pin! If you're using an external reference on the AREF pin, you must set the analog reference to EXTERNAL before calling analogRead(). Otherwise, you will short together the active reference voltage (internally generated) and the AREF pin, possibly damaging the microcontroller on your Arduino board.

    Alternatively, you can connect the external reference voltage to the AREF pin through a 5K resistor, allowing you to switch between external and internal reference voltages. Note that the resistor will alter the voltage that gets used as the reference because there is an internal 32K resistor on the AREF pin. The two act as a voltage divider, so, for example, 2.5V applied through the resistor will yield 2.5 * 32 / (32 + 5) = ~2.2V at the AREF pin.
     
  13. Onkel

    Onkel Гуру

    у внутренних опорников сильный разброс, но достаточно один раз померять референсное напряжение, выставить коэффициент пересчета в программе и будет достаточная точность при питании ардуины хоть 6 в (что не рекомендуется), что 3 В (что уже на грани рекомендуемого)
     
  14. iwizard7

    iwizard7 Нерд

    Спасибо, поразбираюсь
     
  15. iwizard7

    iwizard7 Нерд

    Всем привет. Пытаюсь сделать чтобы опорное считалось по 1.1В. Есть вот такой скетч, но он не работает. Не могу понять в чем проблема. При подключеном аккумуляторе все время кажет 12.15, если нагружаю аккум лампой то 21w ничего не меняется. Измеряю мультиметром напряжение проседает на 2-3 десятки.
    Код (C++):
    int analogInput = 0;
    float vout = 0.0;
    float vin = 0.0;
    float R1 = 100000.0;
    float R2 = 9940.0;
    int value = 0;

    void setup()
    {
      Serial.begin(9600);
         analogReference(INTERNAL);// опираемся на 1.1 вольт
    }
    void loop()
    {
         value = analogRead(analogInput);
         vout = (value * 1.1) / 1024.0;
         vin = vout / (R2/(R1+R2));
         Serial.println(vin);
    }
    Причем если я вывожу в терминал содержимое переменной value то содержимое это равно всегда 1023 и не меняется с нагрузкой или без.
     
    Последнее редактирование: 6 дек 2016
  16. mcureenab

    mcureenab Гуру

    С портом промахнулись:
    int analogInput =0;

    Используйте именованные константы A1... для идентификации аналоговых портов. Имена констант совпадают с маркировкой контактов на плате. Их значения зависят от модели.

    Нет вызова

    pinMode(analogInput, INPUT);
     
  17. iwizard7

    iwizard7 Нерд

    Сменил на A1, результат тот же. Сейчас нашел что "Можно воспользоваться встроенным в ATMega328 источником опорного напряжения в 1.1 В. Если это сделать, то все аналоговые входы будут измерять напряжение от 0 до 1,1 В (1023=1,1В)." У меня с делителя выходит 1.17, похоже поэтому он и кажет 1023 (максимум). Делитель у меня 100ком резистор и 10ком
     
  18. mcureenab

    mcureenab Гуру

    Попробуйте

    analogReference(DEFAULT)
    и
    vout =(value *1.1)/1024.0; заменить на

    vout =(value *5.0)/1024.0;

    ну чтобы делитель напряжения не переделывать.
     
  19. iwizard7

    iwizard7 Нерд

    Я от этого специально ушел, что-бы измерения были более точные и не зависили от входного напряжения.
     
  20. mcureenab

    mcureenab Гуру

    На плате Arduino присутствует стабилизатор напряжения. Ни чем не хуже интегрированного в МК. Он используется в случае питания через колодку и выдает свои 5 В.