1 1. Назначение Устройство Контроля Аккумуляторных Напряжений (далее УКАН) предназначено для: - для визуального котроля напряжения содержания в буфере батареи в режиме реального времени; - для котроля состояний батареи при проведении профилактических мероприятий; - для информирования обслуживающего персонала световой и свуковой сигнализацией о состояниях станционной аккумуляторной батареи и, как следствие, предупреждение возникновения возможных аварий на оборудовании запитанного от батарей; - для защиты станционных аккумуляторов во время разряда при профилактических мероприятиях или аварийных ситуацих от: а) глубокого разряда батареи, и, как следствие, преждевременной потери емкости аккумуляторной батареи и отдельных ее элементов; б) предупреждение обслуживающего персонала о возможных аварийных ситуациях с батареей (короткого замыкания, обрыва питающей линии в месте установки УКАН, отсутствие напряжения буфера от электропитающих устройств); в) предупреждение обслуживающего персонала о возможных аварийных ситуациях с оборудованием электропитающей установки; 2. Технические данные 2.1. УКАН обеспечивает: 1) измерение напряжения батареи в диапазоне от 5В до 80В; 2) минимальная погрешность измерения напряжения в рабочем диапазоне - не лучше 0,035 В; 3) максимальный ток порта ввода / вывода-не более 40 мА; 4) потребляемая мощность прибора не превышает 1Вт; 5) Продолжительность непрерывной работы-неограниченная 2.2. УКАН обеспечивает работу при: 1) отклонении напряжения питания 5±1в (при питании прибора от USB порта ПЭВМ) и 6 до 20В (при питании от отдельного источника питания); 2) температуре внешней среды от 0° до +50° С; 3) относительной влажности воздуха до 80% 2.3. УКАН питается от USB порта ПЭВМ, или отдельного источника питания через внутренний стабилизатор на плате ARDUINO NANO. 3. Состав, настройка и принцип работы УКАН Принципиальная схема прибора изображена на рис.2 Схема подключения и состав прибора изображен на рис. 3 Одной из особенностей работы прибора является очень необычный способ измерения напряжения. Прибор делает около 100 измерений за 5 секунд, сортирует результаты по возростанию и выбирает средний результат. Благодаря этому способу достигается достаточно маленькая погрешность измерения, а точность результатов измерений существенно возрастает. Также добавляет стабильности прибора пересчет измеренного напряжения относительно опорного источника питания на борту платы ARDUINO. На опытном образце 2 стабильность измеренного напряжения без отклонений к третьему знаку после запятой наблюдалась на протяжении нескольких часов. Следует обратить внимание на количество подделок и брака среди этих плат, особенно среди тех, что произведены в Китае – параметры бракованных изделий нестабильны и не подходят к включению в состав прибора. В состав устройства входят делитель входного напряжения от аккумуляторной батареи (14/1) и 1 или 2 канала (в зависимости от назначения в дальнейшей эксплуатации прибора УКАН) вывода: на реле сигнализации и на реле подключения нагрузочного сопротивления (смотри рис.2). Для защиты порта микроконтроллера, резисторы делителя напряжения подобраны таким образом, чтобы максимальный ток сквозь порты платы ARDUINO не превышал 10мА. Коммутация реле выполнена с транзисторной развязкой и дополнительным сопротивлением на порту для ограничения максимального тока сквозь него в случае повреждения ключевого транзистора. Диоды VD1 и VD2 предназначены для защиты выводов в случае ошибки подключения прибора к аккумуляторной батарее. После сборки настройки в схеме прибор требует только по отношению к резисторам делителя (при настройке следует учесть потери на диоде VD1) и подбора по току реле резисторов R5, R6. Для повышения точности прибора после сборки в управляющую программу нужно ввести номиналы сопротивлений делителя, измеренные наиболее точным прибором из имеющихся: float R1 = 43020; float R2 = 3074; Для компенсации погрешности УКАН в управляющей программе прибора можно настроить поправочный коэфициент: float P = 1; который необходимо изменить на процент, на который отличается истенное значение напряжения, измеренное образцовым прибором и показаниями УКАН. (Например истенное напряжение 60В, показания УКАН равны 55,4В, Р =60/55,4 =1,083, следовательно в программе нужно ввести правку «float P = 1,083;» Использование в схеме делителя подстраиваемых резисторов считаю нецелесообразным, вследствие колебаний их параметров со временем и в зависимости от температуры. Если погрешность измерений напряжения сложно уменьшить подбором резисторов делителя или поправочным коэфициентом, вследствие того что отсутствуют необходимые номиналы, или погрешность меняется в зависимости от питающего напряжения или условий окружающей среды, погрешность лучше уточнить и в дальнейшем ее учитывать при обработке данных. Следует понимать, что ПКРСАБ не эталонный прибор, обслуживающему персоналу все равно следует для замеров во время профилактик или разряда станционной батареи использовать поверенные приборы контроля, а устройством УКАН пользоваться в качестве прибора сигнализации. После сборки и настройки элементов устройства, необходимо подключться к плате ARDUINO с помощью программной оболочки ARDUINO IDE или аналогичной и загрузить управляющую программу, в которой следует произвести необходимые настройки под выбранный режим работ и измерений. Следует помнить, сама программа ARDUINO IDE требует определенных настроек: установка драйверов, выбор типа платы, номера и скорости обмена порта – смотри инструкции пользователя выбранной программы и платы. 3 Корректировка программы и загрузка ее к плате ARDUINO занимает около минуты и может проводиться в любое удобное для оператора время перед началом работ. Под прибор следует изготовить плату из одностороннего фольгированного стеклотекстолита, или воспользоваться готовой макетной платой, что значительно упрощает монтаж прибора. Для крепления платы ARDUINO можно использовать доступные коннекторы PBS-15. перечень и количество элементов УКАН приведены в Таблице 1, резисторы пременены типа МЛТ-0,125 ±10%. Транзисторы и реле выбираются в зависимости от наличия, неоходимого типа и токов коммутации. Текст управляющей программы УКАН приведен в Приложении 1, или его можно получить в электронном виде написав письмо на электронный адрес [email protected]. В управляющей программе возможно сделать следующие настройки: Voff = 60В - напряжение неприрывной выдачи сигнализации; Vbad = 0.1В - разность напряжения между измерениями, при которой сработает сигнализация персоналу (при данной разнице становится понятно, что напряжение на батарее начало изменяться в меньшую сторону и батарея нуждается в более детальном контроле обслуживающим персоналом); Time = 300 - время в секундах, на которое отключается звуковая сигнализация после выключения его кнопкой на панеле прибора; Кх = 5 -период проверки Vbad - разность напряжения будет проверяться каждое 5 измерение напряжения, то есть примерно каждые 25 секунд; A_PIN 1-пин A1 ARDUINO предназначен для измерения напряжения батареи; pinRelay 7-пин D7 ARDUINO предназначен для выхода на реле нагрузки; pinAlrm 2-пин D2 ARDUINO предназначен для выхода на реле сигнализации; BUZZER_PIN 6 - к пину D6 подключеатся внутренний буззер звуковой сигнализации bool btnState = !digitalRead(9) – в этой строке (9) это номер пина на который подключается кнопка временной блокировки выдачи звуковой сигнализации. Для измерения напряжения, возможно, выбрать любой удобный пин из аналоговых на плате. Для портов вывода возможно выбрать любой удобный из цифровых. Для удобства монтажа или настройки, для пинов выводов можно выбрать любой и переназначить их в управляющей программе. Величина Vbad связана с величиной Кх - от изменения этих переменных будет зависеть чувствительность прибора. Чем больше Кх, тем больше можно увеличивать Vbad. Следует обратить внимание, что величина Vbad = 0.1 В (при Kх = 5) получена опытным путем - она почти исключает ложные срабатывания прибора и является предельной при разряде. Приведу пример: на тестовой Станционной батарее (аккумуляторы НКГ-160 с остаточной емкостью не более 60% от номинала) после срабатывания сигнализации Vbad >0,1В, у обслуживающего персонала было около 5 минут до момента когда на одном из элементов Станционной батареи напряжение снижалось до критической величины!! Увеличение Vbad и Kх уменьшит риск ложных срабатываний, однако и уменьшит время, за которое может отреагировать персонал. 4 Рисунок 1 – график разряда тестовой батареи 4. Подготовка и начало работы с УКАН Для начала работы с прибором подключите плату ARDUINO к напряжению питания, вход прибора к контролируемой батарее, к выводам выходов цепи сигнализации. На экране прибора через 5 секунд отобразится измеренное напряжение и будет обновляться с интервалос в 5 секунд. При появлении аварийных ситуаций (когда напряжение на батарее снижается со скоростью Vbad или меньше Voff) сработает звуковое оповещение и на дисплее отобразится тип аварии и теккущее напряжение. Если авария сработала по снижению напряжения, то на экране отобразится: А64,8 Если по достижению Voff: b55,4 Отключене выдачи аварийной сигнализации возможно отключить на время установленное в программе Time нажатием кнопки «сброс». Для этого нужно нажать ее и удерживать ее от 5 до 10 секунд пока на экране не изменится индикация – посе первого символа появится точка: А.64,8 b.55,4 После истечения времени Time в случае если аварийной ситуации больше нет экран обнавляется и начинает отображать только напряжение батареи, в противном случае индикация аварии продолжается и вновь включается выдача звуковой сигнализации. Согласно управляющей программе вначале идет проверка по Vbad потом по Voff и если сработала сигнализация и по Vbad и по Voff на экране будет отображаться последняя из сигнализаций. 5 В случае однократного срабатывания сигнализации, по какой-то из проверок на экране сохраняется индикация типа сигнализации до тех пор пока она не будет сброшена нажатием кнопки «сброс». Разумеется после нажатия кнопки «сброс» выдача звуковой сигнализации для вновь появившейся аварии будет невозможна на время Time. Для проверки работоспособности сигнализатора УКАН следует установить в разрыв минусового провода кнопку с нормальнозамкнутыми контактами, при нажатии на которую происходит розрыв провода. На экране сработает сигнализация по Voff. Отключение сигнализации произвести кнопкой «сброс». 4 техническое обслуживание в объем годового ТО должны быть включены следующие мероприятия: - проверка и уточнение погрешности измерения напряжения; - проверка срабатывания реле; - проверка выдачи звукового оповещения. Рисунок 2 Принципиальная схема устройства 6 Таблица 1 перечень элментов обозначение на схеме R1 R2 R3, R4 R5, R6 VD1 – VD4 VT1 - VT2 Rel1 - Rel2 Р1 , Наименование 3,1 кОм 42 кОм 560 Ом Подбирается при наладке КД522Б КТ315 Реле сигнальное 5VDC Дисплей ТМ1637 Буззер 5В пассивный Кнопка без фиксации Количество 1 1 2 2 4 2 2 1 1 1 Примечание 7 8 Приложение 1 #include "TM1637.h" #define CLK 4 #define DIO 3 TM1637 tm1637(CLK, DIO); #define A_PIN 1 // пин A1 на + Акб 12-24В #define NUM_READS 100 #define pinRelay 5 // пин D5 на реле #define pinAlrm 2 // пин D2 на сигнализацию #define BUZZER_PIN 6 // пин D6 на бузер //#define BTN_PIN 9 // D9 кнопка подключена сюда (BTN_PIN --- КНОПКА --- GND) // тут и только тут делаются все настройки прибора!!! float Vbad = 1; // напряжение выпадения 1 банки float Kx = 5; // через сколько измерений по 5 сек проверять разницу напряжений float R1 = 10000; // Сопротивление R1 в ОМАХ float R2 = 830; // Сопротивление R2 в ОМАХ float P = 1; // поправочный коэфициент для програмной подстройки делителя, % от отношения измеренного и истенного float Voff = 30; // напряжение непрерырвной выдачи сигнализации - АКБ сдох float Time = 20; // время в секундах на которое отключается звуковая сигнализация float Tt; float Vcc; float I; float Tv = 0; float Vold = 0; float V; float K = 1; // временная переменная количества проверок const float typVbg = 1.095; // 1.0 -- 1.2 float B; bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; unsigned long prevMillis; unsigned long testStart; void setup() { tm1637.init(); 9 tm1637.set(BRIGHT_TYPICAL); //BRIGHT_TYPICAL = 2, //BRIGHT_DARKEST = 0, //BRIGHTEST = 7; Serial.begin(9600); pinMode(pinRelay, OUTPUT); pinMode(pinAlrm, OUTPUT); digitalWrite(pinRelay, HIGH); digitalWrite(pinAlrm, LOW); testStart = 0; prevMillis = millis(); pinMode(9, INPUT_PULLUP); } void loop() { bool btnState = !digitalRead(9);// проверка нажата ли кнопка if (btnState==1) { testStart = millis(); flag4 = true; Serial.println(flag4); Serial.println("btn on"); } //if (flag4 == 0 && Time >= (millis()/1000)) testStart = (millis() + Time * 1000 + 50); if (Time >= (millis()/1000)) testStart = (millis() + Time * 1000 + 50); Serial.println(testStart); if (flag4 == 1) { if (flag == 1 || flag2 == 1) { Tt = ((millis() - testStart) / 1000); if (Time >= Tt) { flag3 = true; Serial.println(flag3); Serial.println(Tt); } else { flag3 = false; flag4 = false; }} } Vcc = readVcc(); //считывание опорного напряжения V = (readAnalog(A_PIN) * Vcc * R1/R2 * P) / 1023.000; //считывание напряжения АКБ if (K >= Kx) { // проверка подения напряжения на акб 1 раз через Kx раз Tv = Vold - V; if (Tv > Vbad) { // сравнение выпалала ли одна банка flag = true; 10 Serial.println(flag); Serial.println("Vbad"); } else flag = false; Vold = V; K = 1; } else {Tv = 0; K = K + 1;} if (V <= Voff) flag2 = true; else flag2 = false; if ((flag==1) && (flag3==0)) { digitalWrite(pinAlrm, HIGH); tone(BUZZER_PIN, 240, 300); delay (300); tone(BUZZER_PIN, 500, 1000); } else digitalWrite(pinAlrm, LOW); if ((flag2==1) && (flag3==0)) { digitalWrite(pinAlrm, HIGH); tone(BUZZER_PIN, 240, 300); delay (300); tone(BUZZER_PIN, 500, 1000); } else digitalWrite(pinAlrm, LOW); sendData(); // отправка данных в последовательный порт Tv = 0; } void sendData() { unsigned int RAWrpt3 = V*100; // переводим в целое число int8_t Digits[] = {0x00,0x00,0x00,0x00}; // буфер для цифр LED-индикатора Digits[0] = (byte)(RAWrpt3 / 1000) % 10; // раскидываем 4-значное число на цифры Digits[1] = (byte)(RAWrpt3 / 100) % 10; Digits[2] = (byte)(RAWrpt3 / 10) % 10; Digits[3] = (byte)(RAWrpt3) % 10; if (flag4 == 1) { tm1637.clearDisplay(); } if (flag == 1) { if (flag3 == 0) { tm1637.point(false); 11 tm1637.display(0, 10); } else { tm1637.point(true); tm1637.display(0, 10); } } if (flag2 == 1) { if (flag3 == 0) { tm1637.point(false); tm1637.display(0, 11); } else { tm1637.point(true); tm1637.display(0, 11); } } tm1637.point(false); tm1637.display(1, Digits[0]); tm1637.point(true); tm1637.display(2, Digits[1]); tm1637.point(false); tm1637.display(3, Digits[2]); } float readAnalog(int pin) { // read multiple values and sort them to take the mode int sortedValues[NUM_READS]; for (int i = 0; i < NUM_READS; i++) { delay(25); int value = analogRead(pin); int j; if (value < sortedValues[0] || i == 0) { j = 0; //insert at first position } else { for (j = 1; j < i; j++) { if (sortedValues[j - 1] <= value && sortedValues[j] >= value) { // j is insert position break; } } } for (int k = i; k > j; k--) { // move all values higher than current reading up one position 12 sortedValues[k] = sortedValues[k - 1]; } sortedValues[j] = value; //insert current reading } //return scaled mode of 10 values float returnval = 0; for (int i = NUM_READS / 2 - 5; i < (NUM_READS / 2 + 5); i++) { returnval += sortedValues[i]; } return returnval / 10; } float readVcc() { // read multiple values and sort them to take the mode float sortedValues[NUM_READS]; for (int i = 0; i < NUM_READS; i++) { float tmp = 0.0; ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); ADCSRA |= _BV(ADSC); // Start conversion delay(25); while (bit_is_set(ADCSRA, ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both tmp = (high << 8) | low; float value = (typVbg * 1023.0) / tmp; int j; if (value < sortedValues[0] || i == 0) { j = 0; //insert at first position } else { for (j = 1; j < i; j++) { if (sortedValues[j - 1] <= value && sortedValues[j] >= value) { // j is insert position break; } } } for (int k = i; k > j; k--) { // move all values higher than current reading up one position sortedValues[k] = sortedValues[k - 1]; } sortedValues[j] = value; //insert current reading } //return scaled mode of 10 values float returnval = 0; for (int i = NUM_READS / 2 - 5; i < (NUM_READS / 2 + 5); i++) { returnval += sortedValues[i]; } 13 return returnval / 10; }