Разрядно-зарядное устройство для замера емкости АКБ

SLAV_77
Offline
Зарегистрирован: 08.04.2015

 

Здравствуйте уважаемые форумчане!
Помогите пожалуйста "чайнику" создать скечь для устройства заряда-разряда акб для определения их емкости. Покопавшись на просторах интернета нашел готовое устройство на ардуино и скетч, но он не компелируется сообщая об ошибке. Немогу понять в где я незадекларировал RTC?

вот готовый код:



// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <EEPROM.h>
#include <Wire.h>
#include <DS1307.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>


int rtc[7];
byte rr[7];
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
#define RELE_NAGRUZKA 2 //объявляем работу реле нагрузки на пине 2
#define RELE_ZARYADKA 3 //объявляем работу реле зарядки на пине 3
int analogPin = 0;
int flag=0;
float val=0;
float valkoef=0;



void setup () 
{
  DDRC|=_BV(2) |_BV(3);  // POWER:Vcc Gnd
  PORTC |=_BV(3);  // VCC PINC3
  
 RTC.get(rtc,true);
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  lcd.home();
  pinMode(RELE_NAGRUZKA, OUTPUT); //инициируем реле только на выход  
  pinMode(RELE_ZARYADKA, OUTPUT); //инициируем реле только на выход
  lcd.clear();  
  digitalWrite(RELE_NAGRUZKA, HIGH);
  digitalWrite(RELE_ZARYADKA, HIGH);
  RTC.SetOutput(DS1307_SQW32KHZ);
  EEPROM.write (0, rtc[2]); // при старте записываем значение времени, часы
  EEPROM.write (1, rtc[1]); // при старте записываем значение времени, минуты
}

void loop () 
{
 val = analogRead(analogPin); // считываем значение напряжения с аналогового порта
 valkoef=val/74,49; // приводим снятое с аналогового пина значение к обычным вольтам
 RTC.get(rtc,true);
 lcd.setCursor (0,0);
 lcd.print (rtc[2]);
 lcd.print (":");
 lcd.print (rtc[1]);
 lcd.print (":");
 lcd.print (rtc[0]);
 lcd.print (" str");
 lcd.print (EEPROM.read(0));
 lcd.print (":");
 lcd.print (EEPROM.read(1));
 lcd.setCursor (0,1);
 lcd.print (valkoef);
 lcd.print (" ");
 lcd.print (flag);
 
 if (valkoef < 10.72)
   {
    flag=1;
    EEPROM.write(2, rtc[2]); // записыываем время окончания разрядки, часы
    EEPROM.write (3, rtc[1]); // записыываем время окончания разрядки, минуы
   }
 if (flag==1)
 {
   digitalWrite(RELE_ZARYADKA, LOW); // включаем зарядку
   digitalWrite(RELE_NAGRUZKA, HIGH); // выключаем нагрузку
   lcd.print (" stp");
   lcd.print (EEPROM.read(2)); // выводим время окончания разрядки
   lcd.print (":");
   lcd.print (EEPROM.read(3));
 }
   
 if ((valkoef > 10.72) && (flag==0))
 {
   digitalWrite(RELE_NAGRUZKA, LOW);
    }
 else
   {
     digitalWrite(RELE_NAGRUZKA, LOW);
    
   }
  delay(500);
}

а это сообщение об ошибке:

Arduino: 1.6.1 (Windows 7), Плата"Arduino Uno"

zarjd_razrjd.ino: In function 'void setup()':

zarjd_razrjd.ino:26:2: error: 'RTC' was not declared in this scope

zarjd_razrjd.ino:35:17: error: 'DS1307_SQW32KHZ' was not declared in this scope

zarjd_razrjd.ino: In function 'void loop()':

zarjd_razrjd.ino:44:2: error: 'RTC' was not declared in this scope
 

inspiritus
Offline
Зарегистрирован: 17.12.2012

наверно гдетто

после инклюдов должно быть чтотто типа

RTC_DS1307 RTC;

а в секции setup должна быть директива типа 

RTC.begin();

создающая объект RTC

смотрите примеры к своей библиотеке

bwn
Offline
Зарегистрирован: 25.08.2014

И с IDE 1.6 аккуратнее, глючит(((.

Если не в лом, ссылочку на устройство.

reachim
Offline
Зарегистрирован: 08.04.2015

Проверь, есть ли у тебя библиотека RTClib.h, она должна красным подсвечиваться в 05 строке программы

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SLAV_77, судя по скетчу это устройство крайне примитивно, оно не контролирует токи зарядки/разрядки, не контролирует максимальное напряжение зарядки.  И сам скетч написан в стиле новичка.  В целях само-обучения вы бы могли самостоятельно сделать что-то подобное, даже не используя еепром и модуль часов (в них нет особой надобности) . И подходя к цели постепенно , разбив задачу на 2 логические части -зарядка и разрядка.

SLAV_77
Offline
Зарегистрирован: 08.04.2015

Огромное спасибо, всем кто откликнулся! Отвечу всем по порядку. inspiritus пробовал вставлять RTC_DS1307 RTC; после инклюдов и сетапить RTC.begin(); выдает другую ошибку:

Arduino: 1.6.1 (Windows 7), Плата"Arduino Uno"

zarjd_razrjd.ino: In function 'void setup()':

zarjd_razrjd.ino:27:6: error: 'class RTC_DS1307' has no member named 'get'

zarjd_razrjd.ino:36:7: error: 'class RTC_DS1307' has no member named 'SetOutput'

zarjd_razrjd.ino:36:17: error: 'DS1307_SQW32KHZ' was not declared in this scope

zarjd_razrjd.ino: In function 'void loop()':

zarjd_razrjd.ino:45:6: error: 'class RTC_DS1307' has no member named 'get'.

reachim библиотеки перепробовал все которые нашел (сейчас стоит RTClib-master.zip) ничего не меняется и подсвечивается синим, а не красным.

К сожалению ссылку на устройство дать немогу покупал в китае, правда еще не все пришло ( нет твердотельных реле + токового датчика с шунтом). Схема самого устройства (заряда-разряда) взята от сюда: http://habrahabr.ru/post/253143/.  

dimax с вами несовсем согласен по поводу вычисления емкости, ведется запись начала и окончание разряда, и этого вполне хватает для вычисления емкости зная мощьность нагрузки ( правда не  атоматическим способом, но и это можно сделать по степени моего развития). Теперь у меня задача запустить то что есть, а потом по степени развития усовершенствовать. Задача вычисления емкости АКБ предназначенных для ИБП в частном доме в виду частого и долговремменного отключения электричества, чтобы в самый неподходящий момент неоставить источники потребления 1 категории (котел + станция водоснабжения + холодильник) без электроэнергии. В будующем планирую обьеденить автоматическое зарядное устройство (оно у меня есть) и разрядное устройство в один корпус, создав таким способом универсальное зарядно-рязрядное устройство, работающее по разным программам (как вы и предлагаете).

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

master удали)) должно быть просто RTClib

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SLAV_77,  дело ваше конечно.  Но повторяя неграмотно и неоптимально составленный код вы наносите вред своему собственному развитию. Даже если не принимать во внимание некоторые упрощённые подходы автора к измерению ёмкости, и совершенно чайниковый скетч, то неужели вы считаете нормальным -имея микроконтроллер вычислять ёмкость аккумулятора в уме? Вычитать время, перемножать на ток? Непонятно, как модераторы Хабра пропускают такие материалы к публикации.. В часах тут вообще нет никакого смысла, вполне достаточно настроить таймер на прерывание каждую секунду, и считать время инкременируя секунды. Так даже удобнее будет вычислять ёмкость. Записывать в еепром тоже отпадёт надобность.

SLAV_77
Offline
Зарегистрирован: 08.04.2015

dimax я с вами во всем согласен, но я же пока "чайник" поэтому и приходится использовать "чайниковый" проэкт в надежде что от этого что-то в голове появится. Просто думаешь как лучше, а получается как всегда. Но если у вас есть предложение получше готов обсудить этот вопрос!?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SLAV_77, зависит от того, есть ли у вас достаточный опыт для такой работы. Иначе проще купить Imax B6 и не париться. Если всё-же хочется своими руками, то начните создавать с ноля поэтапно, это сильно облегчает задачу. Думаю вам многие, в том числе я помогут. Я бы предложил сначала подготовительную часть: (1) Выбор метода измерения напряжения, выбор метода и средств измерения тока. (2) сборка и калибровка измерителя тока и напряжения. (3) дополнить функцией для подсчёта секунд, тестовый вывод на дисплей минут и часов из функции подсчёта секунд. (3) выбор алгоритма функции измерения ёмкости, выбор типа нагрузки, практическая реализация. (4) полностью реализовать функцию подсчёта ёмкости.(5) выбор алгоритма переключения между функциями зарядки и подсчёта ёмкости. (6) реализация. (7) дополнение функцией измерения внутреннего сопротивления аккумулятора. (8) реализация полного автоматического цикла (дозарядка-подсчёт ёмкости, снова зарядка, измерение внутреннего сопротивления)

Займитесь пока первым пунктом. Тут есть варианты. Лучше всего использовать специализированные микросхемы или готовые модули , я о таком варианте писал недавно.   Если хорошо дружите с паяльником, -можно спаять самостоятельно усилитель для шунта. В некоторых случаях можно взять шунт сопротивлением побольше, и обойтись без усиления. Но об этой возможности можно судить зная всю конкретику.  Можно применить для измерения тока популярный ACS712, но точность будет сильно хуже, я бы не советовал. Напряжение  можно измерять встроенным АЦП, в этом случае желательно использовать внутреннее опорное и оверсемплинг. Решайте, каким путём пойдёте.

 

SLAV_77
Offline
Зарегистрирован: 08.04.2015

dimax огромное спасибо вам за подсказку-напутствие. По первому пункту буду использовать датчик тока на  ACS712(на 30А)+ шунт DC 50A 75mV(манганин), а измерение напряжения на обычном делителе, но пока все это идет или "ползет" из приисподней. Я не расматривал  использование INA219 по вашей подсказке, но если честно я как-то побаиваюсь после нескольких неудачь использование шины I2C, хотя предложение лучший вариант чем мой. Кое что уже реализовывал включение-выключение реле+секундомера после появления определенного значения на АЦП, но секундомер считает до 10-ти часов потом сбрасывается и пошел по новой в моем случае это не есть гуд, т.к. разряд при номинальной нагрузке длится больше 12 часов и больше чем привязать часы реального времени на DS1307 в голову ничего не приходит (это все пока для разрядки АКБ).

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SLAV_77, поясните поподробнее о ваших планах на "ACS712(на 30А)+ шунт DC 50A 75mV" Для acs712 шунт не нужен. А для вышеуказанного шунта нужен усилитель с коэф.усилиния не менее 15.

По поводу секундомера -очевидно вы не тем путём пошли, и поэтому делате неправильные выводы. Если запрограммировать таймер на прерывание каждую секунду, а в теле прерывания инкреминировать переменную u_long, то возможностей счёта хватит на 136 лет. По-моему более чем достаточно для зарядного устройства  :)

 

SLAV_77
Offline
Зарегистрирован: 08.04.2015

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

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
boolean sets = false;
unsigned long cur_millis , lastTick, setTick = 0; 
int sec, mins, hour = 0; 


LiquidCrystal_I2C lcd(0x27,16,2);
 
void setup() {
  lcd.init(); // Инициализация дисплея, проверка правильности подключения 
  lcd.backlight(); // Включение подсветки экрана
  
 
  sets = true;
}
 
void loop() {
  cur_millis  = millis(); //time
 
  if (cur_millis - lastTick >= 1000) {
    lastTick = cur_millis;
    sec++;
 
    if (sec >= 60) {
      mins++;
      sec = 0; 
    }
 
    if (mins >=60) {
      hour++;
      mins = 0; 
    }
 
    if (hour >=24) {
      hour=0;
      mins = 0; 
    }
 
    lcd.setCursor(0,0);
    lcd.print("HOUR");
    lcd.setCursor(1,1);
 
    if (hour < 10) {lcd.print("0");}
    lcd.print(hour);
    lcd.print(":");
    if (mins < 10) {lcd.print("0");}
    lcd.print(mins);
    lcd.print(":");
    if (sec < 10) {lcd.print("0");}
    lcd.print(sec);
  }
  
}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SLAV_77, чуть погодите с кнопкой. Для начала разнесите всё в функции, вывод на lcd -Отдельная функция, счёт секунд и преобразование их в минуты и часы -отдельная функция. Иначе скоро у вас loop() разрастётся так, что будет проблематично в нём что-то понять. Для разрешения счёта времени сделайте ещё один bool  флаг. Внутренности loop() после этих процедур должны выглядеть примерно так:

loop() {
if(time_count_flag) time_count(); // если разрешён счёт времени - пойти подсчитать
lcd_work() ;// функция обслуживания вывода на дисплей
}

После этого выберите как будете бороться с дребезгом, программно или конденсатором (своё мнение я недавно писал тут) Напишите обработчик кнопки и продолжим )

SLAV_77
Offline
Зарегистрирован: 08.04.2015

dimax доброго вам времени суток! Несколько вечеров сижу и парюсь с bool флагами, но так ничего и не понял. Скечь по разрядке кое что уже обрисовывается, только проблема снова не понимаю как остановить функцию счета. С кнопки запускается реле включаеся только по заданному параметру, а при выключении (по понижению напряжения ниже заданного параметра) счет не останавливается. Вот скетч:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define button 7 // Кнопка для Запуска/Остановки (нажатие = замыкание на GND)
#define delay_button 200 //Задержка в мс после нажатия кнопки, поскольку мгновенно
#define RELAY 3   
int analogPin = 0;    // select the input pin for the potentiometer
bool start = true, work = false;
unsigned long cur_millis , lastTick, setTick = 0;
int sec, min, hour = 0; 
float val=0;
float valkoef=0;

LiquidCrystal_I2C lcd(0x27,16,2);
 
void setup() 
{
  lcd.init(); // Инициализация дисплея, проверка правильности подключения 
  lcd.backlight(); // Включение подсветки экрана
  pinMode(RELAY,OUTPUT);   
  pinMode(button,INPUT);  
  digitalWrite(button, HIGH); //подключить внутренний подтягивающий резистор 
  
}
 
void loop()
{
  val = analogRead(analogPin);// считываем значение напряжения с аналогового порта
  valkoef=val/74,49;// приводим снятое с аналогового пина значение к обычным вольтам
  lcd.setCursor(0,0);// ставим курсор на начало верхней строки
  lcd.print(valkoef);
  lcd.print (" "); // Выводим на экран значение с аналогового входа 
  lcd.setCursor(1,1);
    if (hour < 10) {lcd.print("0");}
    lcd.print(hour);
    lcd.print(":");
    if (min < 10) {lcd.print("0");}
    lcd.print(min);
    lcd.print(":");
    if (sec < 10) {lcd.print("0");}
    lcd.print(sec);
    lcd.print(" ");
  {  
   if (valkoef > 10.72)
    {
     digitalWrite(RELAY,HIGH);//если показатель  больше 10.72, включаем реле
       
  }    
   if (valkoef < 10.72)
    {
     digitalWrite(RELAY,LOW);//если показатель  меньше 10.72, выключаем реле
     
    }    
   if (!((digitalRead(button))&&start)) //Ждем нажатия
  {
  start = false; // Отключаем проверку нажатия
  work = true; // Запускаем часы 
  delay(delay_button);
  cur_millis  = millis(); //time
  } 
  if (cur_millis - lastTick >= 1000) // считаем время разряда
   {
    lastTick = cur_millis;
    sec++;
     if (sec >= 60) 
     {
      min++;
      sec = 0; 
     }
    if (min >=60) 
     {
      hour++;
      min = 0; 
     }
    if (hour >=24) 
     {
      hour=0;
      min = 0; 
     }
   }}
  
  delay(500);
}

 

777Andrej
Offline
Зарегистрирован: 09.04.2014

 я сделал такое разрядное. ибо зарядку можно сделать любую. https://www.youtube.com/watch?v=ZAnqSbdpk-w

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SLAV_77, я вам в сообщении #9  и  #13  написал с чего нужно начать.

Timon_1
Offline
Зарегистрирован: 15.03.2015

Интересно, интересно.... SLAV_77,  изложи более развернуто замысел. для каких АКБ сия затея. Может наши цели совпадут. Тогда 2 чайника вместе будет лучше чем 2 чайника по отдельности.

SLAV_77
Offline
Зарегистрирован: 08.04.2015

Это затея для мощьных АКБ от ИБП для домашнего эл.снабжения. Я писал об этом в посте выше. Но думаю для автомобильных тоже вполне подойдет. Если есть интерес могу описать по какому алгоритму оно должно работать, но только пока для разряда. 

Timon_1
Offline
Зарегистрирован: 15.03.2015

у меня целью является заряд разряд свинцово-кислотных стартерных АКБ. вот что по теме нашел: http://meandr.org/archives/5916. не знаю даже. или свое городить или попробовать это повторить

SLAV_77
Offline
Зарегистрирован: 08.04.2015

А скечь на сие устройство вы копировали?

Timon_1
Offline
Зарегистрирован: 15.03.2015

Там скетча как такового нет. там и ардуины нет. прошивка hex есть.

SLAV_77
Offline
Зарегистрирован: 08.04.2015

кто знает как стабилизировать показания с резестивного делителя? Все было в норме пока не открыл форточку чтобы проветрить непрошло и минуты показания поплыли в сторону ( - ). Я понимаю что это все дело в резисторах но как с этим боротся? И кто сталкивался с таким сенсором http://ru.aliexpress.com/item/5pcs-lot-Voltage-Detection-Current-Detecti...?