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

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

  1. iwizard7

    iwizard7 Нерд

    Если я запитываю от USB порта компа то напряжение которое измерят ардуина и выдает в терминал скачет (что то типа 12.57,12.55,12.56,12.57...) Пытаясь как раз от этого избавится я и решил брать опорное 1.1
     
  2. rkit

    rkit Гуру

    Это гораздо сложнее и не стоит труда.
     
  3. iwizard7

    iwizard7 Нерд

    А как тогда поступить? если значения прыгают то и реле отрабатывает не правильно. На нижнем значении напряжения где должна отключится нагрузка и включится зарядка из-за этих скачков реле дергаются то одно то другое
     
  4. iwizard7

    iwizard7 Нерд

    Как вариант придется стабилизировать питание ардуины
     
  5. rkit

    rkit Гуру

    Написать программу лучше.

    Ничего не изменит.
     
  6. iwizard7

    iwizard7 Нерд

    Предложите тогда хотя бы принцип измерения для "лучшей программы" если уж отвечаете
    Как раз все это и меняет, при питании от стабилизированного источника показания никуда не прыгают и все отрабатывает на отлично.
     
  7. mcureenab

    mcureenab Гуру

    У вас ошибка измерений в четвертом разряде!!! Резисторы в делителе напряжения погрешность больше вносят.
    Если эти случайные колебания дестабилизируют работу устройства, добавьте гистерезис.
     
  8. rkit

    rkit Гуру

    Принцип такой же. Логика работы программы другая. Она не должна переключаться туда-обратно от скачков на две сотых вольта. Переключилась в режим зарядки - пусть работает до конца зарядки.
     
  9. mcureenab

    mcureenab Гуру

    Собственно в исходном коде гистерезис присутствует:

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

      if (vin > 13.70) {      // Напряжение включения заряда
        digitalWrite(7, LOW);
        digitalWrite(8, HIGH);
      }
     
    В диапазоне [10.4, 13.7] состояние не меняется даже если напряжение уже вернулось в пределы диапазона.
     
  10. iwizard7

    iwizard7 Нерд

    Это я понимаю, реализовать не могу.По идее как то нужно загрубить показания до десятых наверное
     
  11. mcureenab

    mcureenab Гуру

    Можно сохранить предыдущее значение датчика и если новое значение отличается от него меньше чем на малую величину d, то никаких управляющих воздействий не выполнять. В том числе и не обновлять предыдущее значение датчика. Ну разве что на экран можно вывести текушее напряжение, если это требуется.
     
  12. rkit

    rkit Гуру

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

    Это не гистерезис, это просто переключение по порогам.
     
  13. mcureenab

    mcureenab Гуру

    Фильтр шума.

    Код (C++):
    // Параметры программы
    const int d = 3;        // Радиус шума датчика
    const float R1 = 100000.0;    // Значение резистора R1 (100K)
    const float R2 = 10000.0;    // Значение резистора R2 (10K)
    const float Vbase  = 5.0;    // Опорное напряжение
    ...

    void loop()
    {
      static int value0 = 0;        // Предыдущее значение датчика
      const int value = analogRead(analogInput);    // Новое значение датчика
      const boolean changed = d < abs(value - value0);
        if(changed) value0 = value;        // Чтобы исключить медленный дрейф значения.
      const float vout = (value * Vbase) / 1024.0;    // Выходное напряжение делителя до 5В
      const float vin = vout / (R2 / (R1 + R2));
        if(changed){  // Значение существенно изменилось. Проверим, что нужно сделать.
    ...
        }
        // Действия, выполняемые независимо от изменения значения.
    ...
    }
     
     
    Последнее редактирование: 6 дек 2016
  14. mcureenab

    mcureenab Гуру

    Это программная реализация триггера Шмидта. А триггер Шмидта как раз создает гистерезис.
     
    iwizard7 нравится это.
  15. iwizard7

    iwizard7 Нерд

    Спасибо! сейчас буду разбираться
     
  16. rkit

    rkit Гуру

    Триггер шмидта его не создает, он работает по принципу петли гистерезиса.
    А тут принцип работы другой. Хоть и результат одинаковый.
     
  17. iwizard7

    iwizard7 Нерд

    Подскажите пожалуйста как это сделать правильно ?
     
  18. iwizard7

    iwizard7 Нерд

    В данный момент скетч выглядит так :
    Код (C++):
    //===================Библиотеки===================

    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x20,16,2);  // Настройка параметров дисплея

    //===================Переменные===================

    int analogInput = 1;  // Пин (аналоговый) подключения делителя напряжения
    int RZ = 8;           // Пин подключения реле заряда
    int RR = 10;          // Пин подключения реле разряда
    float R1 = 100000.0;  // Значение резистора R1 (100K)
    float R2 = 10000.0;   // Значение резистора R2 (10K)
    float UPV = 14.50;    // Порог заряда АКБ
    float DWV = 10.80;    // Порог разряда АКБ
    float vout = 0.0;
    float vin = 0.0;

    //===================Переменные для усреднения===================

    const int numReadings = 20;
    int readings[numReadings];      // данные, считанные с входного аналогового контакта
    int index = 0;                  // индекс для значения, которое считывается в данный момент
    int total = 0;                  // суммарное значение
    int average = 0;                // среднее значение


    void setup() {
      Serial.begin(9600);

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

      pinMode(RZ, OUTPUT);          // Реле заряда как выход
      pinMode(RR, OUTPUT);          // Реле разряда как выход
      pinMode(analogInput, INPUT);  // Аналоговый как вход

      for (int thisReading = 0; thisReading < numReadings; thisReading++)
        readings[thisReading] = 0;

    }
    void loop() {

    //===================Процедура усреднения===================

      total= total - readings[index];            // берем последнее значение
      readings[index] = analogRead(analogInput); // которое было считано от сенсора:
      total= total + readings[index];            // добавляем его к общей сумме:
      index = index + 1;                         // продвигаемся к следующему значению в массиве:
      if (index >= numReadings)                  // если мы в конце массива
      index = 0;                                 // возвращаемся к началу:          
      average = total / numReadings;             // вычисляем среднее значение:

    //===================Процедура чтения данных с аналогового порта===================
      vout = (average * 5.0) / 1023.0; // Выходное напряжение делителя до 5в
      vin = vout / (R2 / (R1 + R2));
      if (vin < 0.09) {
        vin = 0.0;
          Serial.println("Battery not connected!!!");
      }
      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(RZ, HIGH);
        digitalWrite(RR, LOW);

    lcd.setCursor(7, 1);
      lcd.print("<-");
      }

      if (vin >= UPV) {             // Разряд
        digitalWrite(RZ, LOW);
        digitalWrite(RR, HIGH);
     
    lcd.setCursor(7, 1);
      lcd.print("->");

      }
      delay (500);

    }
     
    Теперь нужно к нему прикрутить паузу и навремя остановки отключать нагрузку/зарядку, и после паузы измерять напряжение.