PCCar.ru - Ваш автомобильный компьютер

Вернуться   PCCar.ru - Ваш автомобильный компьютер > MP3Car ТехИнфа > AndroidCar > Питание

Ответ
 
Опции темы Поиск в этой теме
Старый 02.05.2018, 17:17   #11
mazay66
Старший Пользователь
 
Регистрация: 17.10.2015
Город: Санкт-Петербург
Регион: 78, 98
Машина: Рено Колеос
Сообщений: 647
mazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to all
По умолчанию

Цитата:
Сообщение от oleg707 Посмотреть сообщение
Ребят, нужны советы.
При сборке БП5mini есть такой момент, что управление дс-дс, который идёт на зарядку и на хаб происходит через предназначенный для этого производителем контакт на микросхеме преобразователя ( EN).
То есть нужно подпаяться к этому контакту на микросхеме. Это и есть тот проводок на фото.
Появилась мысль убрать выход +12В на видео регистратор и освободившийся канал включить на управление дс-дс зарядки и хаба, как это сделано в дс-дс, питающим батарею планшета.
Не вижу особой разницы в методе получения +5В для питания хаба. Оба варианта приемлемы. Зачем менять отработанную схему? Хотя "хозяин-барин". Я, например, знаю точно, что организовать питание планшета с необходимыми задержками можно на простом таймере с транзистором. Без ардуино и проца. А контроль за напряжением бортовой сети выполнять через контакт (EN) подобрав, соответствующим образом делитель напряжения. Ну это другая история. Каждый вариант БП имеет права быть.
mazay66 вне форума   Ответить с цитированием
Старый 02.05.2018, 19:48   #12
oleg707
Гуру
 
Аватар для oleg707
 
Регистрация: 16.04.2014
Возраст: 40
Город: Gdynia
Регион: другой - для добавления сообщить ab
Сообщений: 2,548
oleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond repute
По умолчанию

Цитата:
Сообщение от mazay66 Посмотреть сообщение
Не вижу особой разницы в методе получения +5В для питания хаба. Оба варианта приемлемы. Зачем менять отработанную схему? Хотя "хозяин-барин". Я, например, знаю точно, что организовать питание планшета с необходимыми задержками можно на простом таймере с транзистором. Без ардуино и проца. А контроль за напряжением бортовой сети выполнять через контакт (EN) подобрав, соответствующим образом делитель напряжения. Ну это другая история. Каждый вариант БП имеет права быть.
Одному надо 11,9в и 2 часа задержки, другому 11, 4 и 2 суток. А если ещё хочется поэкспериментировать с задержками...
Так что я без проца уже никуда, посмотри программу, там под тысячу строк кода. Причём эту логику ни одно аппаратное решение не повторит.

Обработанная и та, и та схема. Канал на батарею так сделан, просто подали питание через интеллектуальный ключ, дс-дс включился.

Мнение "Зачем менять отработанную схему?"засчитано.
oleg707 вне форума   Ответить с цитированием
Старый 02.05.2018, 21:09   #13
mazay66
Старший Пользователь
 
Регистрация: 17.10.2015
Город: Санкт-Петербург
Регион: 78, 98
Машина: Рено Колеос
Сообщений: 647
mazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to all
По умолчанию

Полностью согласен с тем, что запросы разные. Только нет секрета в том, что часть логики можно выполняться не блоком питания, а за счет софта установленного в планшете. Таскер прекрасно выключит планшет хоть через 2 минуты, хоть через 2-е суток, хоть через 2 месяца. Зачем "рубить" для этого питание материнки с БП?
mazay66 вне форума   Ответить с цитированием
Старый 02.05.2018, 22:53   #14
oleg707
Гуру
 
Аватар для oleg707
 
Регистрация: 16.04.2014
Возраст: 40
Город: Gdynia
Регион: другой - для добавления сообщить ab
Сообщений: 2,548
oleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond repute
Talking

Цитата:
Сообщение от mazay66 Посмотреть сообщение
Полностью согласен с тем, что запросы разные. Только нет секрета в том, что часть логики можно выполняться не блоком питания, а за счет софта установленного в планшете. Таскер прекрасно выключит планшет хоть через 2 минуты, хоть через 2-е суток, хоть через 2 месяца. Зачем "рубить" для этого питание материнки с БП?
Да, я тоже так думал. Пока зависший планшет за выходные не высадил мне аккумулятор, а ехать надо было срочно.
oleg707 вне форума   Ответить с цитированием
Старый 02.05.2018, 23:17   #15
mazay66
Старший Пользователь
 
Регистрация: 17.10.2015
Город: Санкт-Петербург
Регион: 78, 98
Машина: Рено Колеос
Сообщений: 647
mazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to allmazay66 is a name known to all
По умолчанию

Не убедительный аргумент. Пошли "по второй кругу". Двумя постами выше сказано про использование контакта (EN). Он отключит питание планшета в аварийной ситуации.
mazay66 вне форума   Ответить с цитированием
Старый 03.05.2018, 00:02   #16
oleg707
Гуру
 
Аватар для oleg707
 
Регистрация: 16.04.2014
Возраст: 40
Город: Gdynia
Регион: другой - для добавления сообщить ab
Сообщений: 2,548
oleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond repute
По умолчанию

Цитата:
Сообщение от mazay66 Посмотреть сообщение
Не убедительный аргумент. Пошли "по второй кругу". Двумя постами выше сказано про использование контакта (EN). Он отключит питание планшета в аварийной ситуации.
Тут надо два круга объединять ))
С одной стороны имеем зависший планшет и аварийную защиту от полного разряда ( аппаратное решение), таймер на 555? для отключения каждого канала

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

Плюс мне нужно передергивание питания на хаб при каждом включении зажигания и хаба, независимый контроль REM с отключением через 30 минут при включении зажигания и не отключением при заведенном авто, ... ну и далее по списку ))))

К сожалению аппаратное решение давно не удовлетворяет моих запросов.

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

Последний раз редактировалось oleg707; 03.05.2018 в 00:47.
oleg707 вне форума   Ответить с цитированием
Старый 03.05.2018, 09:15   #17
skanch
Модератор
 
Аватар для skanch
 
Регистрация: 19.01.2010
Возраст: 58
Город: Санкт-Петербург
Регион: 78, 98
Сообщений: 2,645
skanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant futureskanch has a brilliant future
По умолчанию

Цитата:
Сообщение от mazay66 Посмотреть сообщение
...Я, например, знаю точно, что организовать питание планшета с необходимыми задержками можно на простом таймере с транзистором. Без ардуино и проца.
Как вариант имеет право на жизнь. Правда немного "громоздко" получается - на каждый управляемый канал нужно две микросхемы - таймера с обвязкой (одна на задержку включения, вторая на задержку выключения), плюс ключи для коммутации. А еще и "привязать" общую задержку на выключение во время кручения стартером... Мне - совсем не программисту проще использовать контроллер. Но, как правильно заметил - "хозяин-барин"... Вариантов исполнения может быть много и каждый выбирает конкретно под себя.
P.S. Я экспериментировал на микросхеме - таймере MIC 1555. И размер для меня подходящий, и обвязки минимум. Но остановился всё-таки на использовании контроллера...

Последний раз редактировалось skanch; 03.05.2018 в 10:18.
skanch вне форума   Ответить с цитированием
Старый 11.05.2018, 01:41   #18
oleg707
Гуру
 
Аватар для oleg707
 
Регистрация: 16.04.2014
Возраст: 40
Город: Gdynia
Регион: другой - для добавления сообщить ab
Сообщений: 2,548
oleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond repute
Exclamation важное обновление прошивки.

пока в статусе бета тестирования.
m28 - перенесена обработка режимов АСС (вкл, вЫкл) в отдельнее функции.
Добавлены настройки для пользователя ( выключать ли питание на хаб при кручении стартером,
убирать ли массу с IDюсб = OTG при кручении стартером)
m29 - добавлена задержка на определение, крутим ли мы стартером и прекратили ли крутить. Отдельной переменной не создавал, искать по переменной STARTUEM

m30 - добавлена возможность канал датчика холла подключать к физической кнопке питания планшета
( для тех, у кого нету датчика холла но хочется подключится к кнопке питания для автоматического включения/выключения экрана).

PHP код:
const boolean HALL_as_power_Switch 0;       // 0 - используем ДХ как обычно. 1 - вместо ДХ подключаем кнопку питания планшета. 

Если подключено как КНОПКАто задержка перед нажатием "кнопки" 
после включения АСС это SLEEP_timer_pri_vkl_ACC,
 
а после вЫключения это  SLEEP_timer_pri_vykl_ACC
Удержание нажатия 0,

PHP код:
byte ver 30;// БЕТА( чем больше цифра, тем новее)
byte TipBlokaPitania 255// 177 - BP7. 255 - BP5mini //выбор типа блока питания.
// дата правки 10.05.18.2326

// для 5mini версии блока питания. 
// скетч проверен и записан на версии ардуино IDE 1.9.0  1,8,1 win7, 1.63 xp
//Перед прошивкой скетча убедитесь в наличии нужных библиотек,например  d:\777\Soft\arduino\arduino-1.6.11\libraries\LiquidCrystal_I2C\  https://github.com/enjoyneering/LiquidCrystal_I2C например
//в версии T04 добавлена поддержка дисплея Adafruit_SSD1306 128*64  Библиотеки (2 штуки ): https://codeload.github.com/adafruit/Adafruit_SSD1306/zip/master  https://codeload.github.com/adafruit/Adafruit-GFX-Library/zip/master
//в версии m25 добавлена обязательная библиотека JeeLib library  https://github.com/jcw/jeelib .
// НЕДОСТАЮЩИЕ БИБЛИОТЕКИ СКАЧАТЬ И CКОПИРОВАТЬ В ПАПКУ libraries, например  d:\777\Soft\arduino\arduino-1.6.11\libraries\ .
/* _
хотелки


______Сделано__________________________________________________
.
Контроль напряжения АКБ машины.
вывод информации на внешний дисплей по I2C,  библиотека вывода на экран https://github.com/enjoyneering/LiquidCrystal_I2C  и http://elchupanibrei.livejournal.com/27443.html
если в скетче в названии 0x27, значит библиотека старая.
активный вотчдог,
программная защита its716G(statepin)-тестово,
умное мигание встроенным светодиодом, в зависимости от напряжения АКБ и состояния АСС.
усреднение замеров по напряжению ACC и AKB, по 5 замерам.
информация на дисплее обновляется не постоянно, а каждые 350мс ( 0,35 с), чтобы не мельчешить.
Управление REM: если напруга батареи больше UrabotyREM (11.8 В), то включаем еще и усилитель звука (выход REM) /но включаем его только на 30-60мин, если не заведены. После заводки счетчик обнуляется.
v92 сделанъ плавный пуск - определяем нужное состояние пинов без их предварительного дергания в начальное нулевое.
v94 сделанъ вывод на экран через переменную, а не напрямую. ЭТО позволило выводить информацию ЕЩЕ И В КОМ ПОРТ!!! <<<<<<<========================================
v94 Сделана задержка включения REM после холодного запуска,  15с. Через 10 с после начала загрузки идёт инициализация звуковой, в этот момент слышен ПУК
t00 новая ветка блока, по факту продолжение старой.
t02 поскольку аптаймблока в машине превысил 9999 минут, то переделан вывод аптайма 000:00 ( часы : минуты)
t03 дисплей тухнет через 3 сек после операции завершения.
t04 добавлена поддержка дисплея Adafruit_SSD1306 128*64 (тестово). Библиотеки (2 штуки ): https://codeload.github.com/adafruit/Adafruit_SSD1306/zip/master
                   Без 2х библиотек одновременно работать не будет                    https://codeload.github.com/adafruit/Adafruit-GFX-Library/zip/master
t06 обработка напряжений выше 15,5 ( тушим экран и выключаем усилок)
t07 в войд сетап задержки по 0,1с для инициализации дисплеев. Изменен алгоритм выключения - сначала тушим экран, потом все остальное( для таскера, чтобы паузу ставил и плей жал)  
                        выключен Serial.print. display2.begin(SSD1306_ - перекинута инициализация на включение зажигания - 318 строка
t08- ничего
t09 - перенесена строка  проверки заведённой авто, в конец, перед проверкой перезаряда. 
t10 - перешел на другую библиотеку для 1602 дисплея( newE) https://github.com/enjoyneering/LiquidCrystal_I2C. 128*64 не проверял.
t11 - в связи с тем, что у меня дребезжит контактная группа в машине, изменён алгоритм выключения выхода REM 
t12 - возможность калибровки с записью в еепром, переделан метод вывода на дисплей ( теперь через две функции (формирования строк и непосредственно вывода.), а не в основном цикле), убрн вотчдог, как не имеющий практического смысла( пока что просто заккоментирован).
t13  поправлена Логика работы REM = когда стартуем flagREM = 3 Обработка логики работы REM в 538 строках.
t14 - введена новая переменная timeUntilBATOff = время до выключения питания на батарею планшета после выключения зажигания.  24ч = 86400000 (3600000 - 60мин) (60000 - 1 мин)(10800000=3ч) (1800000=5ч) (2суток = 172800000) (4суток = 345600000) 
                               timeUntilALLOff = время до полного выключение блока,  после выключения зажигания (ACC)  ((самозапитка для регистратора)- чтобы легче было менять это время в начале скетча.
      увеличено время поддержки планшета включённым-timeUntilBATOff ( 2 суток после выкл АСС и еще 2 суток после этого до полного выключения блока)    
                           
m01-05 - Новая версия БП5mini. Переход на новые, хорошо себя зарекомендовавшие, дс-дс (mini360). Датчик холла и отг теперь управляются специализированной микросхемой-твердотельным реле. Из-за неё же теперь потеряна совместимость прошивок на БП5 (поскольку на управление холлом теперь нужен инверсный сигнал).  Поэтому уже заодно поменял местами пины управления ОТГ и ХОЛЛА (физически). Фишка полностью совместима с БП5, БП4, БП3.
m6 - обработка статуса выхода REM переведена в отдельную функцию                           
m7 - поменян порядок включения элементов и их тайминги. Тестово. По идее, должно быть стабильнее, либо вообще никак не повлияет. Убраны лишние закомментированны строчки.
m11 - отг включаю сразу.
m12 - Сделал все основные тайминги настраиваемыми в начале скетча. Отдельно на включение, отдельно на выключение. Искать по строке ______НАСТРОЙКИ ТАЙМИНГОВ!!!______.
m14 - теперь тайминги в const unsigned long. В настройках скетча можно включить ресет хаба после каждого включения зажигания( reset_HUB_on_power_on )= передёргивать ли хаб при каждом включении зажигания, для решения проблемы с изикапом (STK1160) 1 - после ВКЛ АСС включить хаб, выключить на 0,5с и включить опять. 0 - просто включить хаб.
m15 - добавил тайминг timeWhileAkbLow = 40000; в настройки, увеличил с 20до 40с, для машин с функцией подсветки пути домой.    //время, через которое начнётся полное выключение блока когда напряжение на АКБ очень низкое. 
m18 - перевел все основные значения напряжений, таймингов и пинов на переменные.  Облегчение портирования на разные аппаратные платформы. ----> Подготовка совместимости с БП7.
m19 - более дружественные комментарии.
m20-22 - переписывание скетча, чтобы не выводить через I2C шину информацию, для экономии энергопотребления и совместимости с БП7. Изменены режимы моргания встроенного светодиода ардуины ( тоже даёт экономию при выключенном зажигании 0,005А). Добавлено время обновления I2C дисплея в настройках пользователя.
m23 - исправлено. иногда не выключалась самозапитка при севшем АКБ! теряется 1 байт в конце PORTBregistr. Поправил - пока стандартными командами в void UPRAVLENIE_PINAMI_BPV.
m24-26 - оптимизация кода и комментариев. 
m27 - добавлен спящий режим для атмеги при выключении зажигания. Уменьшено энергопотребление блока питания. когда запретили работу I2C шины, запускаем сон каждый цикл(loop) на 0,1 сек.                                                                                  ________________________________________________________________ 
m28 - перенесена обработка режимов АСС (вкл, вЫкл) в отдельнее функции. Добавлены настройки для пользователя ( выключать ли питание на хаб при кручении стартером, убирать ли массу с IDюсб = OTG при кручении стартером) 
m29 - добавлена задержка на определение, крутим ли мы стартером и прекратили ли крутить. Отдельной переменной не создавал, искать по переменной STARTUEM
m30 - добавлена возможность канал датчика холла подключать к физической кнопке питания планшета ( для тех, у кого нету датчика холла).
 собственное потребление блока по 12 вольтам, без планшета (для БП5mini)
                                                    - при 10В +30 и +15 выключены                              = 0,014-0,017 А  ( меньше, если выпаять светодиоды с ардуины; также много из этого потребляет CH340G)
                                                    - при 12В +30 и +15 включены                               = 0,056-0,060 A
                                                    - при 12В +30 включены +15 выключены (при питании батареи) = 0,020-0,021 A
________________________________________________________________
поведение встроенного светодиода
    низкое напряжение АКБ авто                                         - коротко моргает
    нормальное напряжение АКБ авто, ACC выключено.                     - быстро моргает
    нормальное напряжение, включено ACC, рабочий режим.                - медленно моргает 


ПРИМЕЧАЕНИЯ
->  strcpy(strokaIIold,strokaII); // strokaIIold = strokaII; так нельзя!!! надо так:  strcpy(strokaIIold,strokaII); // копируем новую строку в старую 
*/ 
//***************************************************************************************************************************************************
// Массив режимов работы светодиода
byte modes[] = {
  
0B00000000//Светодиод выключен
  
0B11111111//Горит постоянно
  
0B00111111//Мигание по 0.8 сек
  
0B00000001//Короткая вспышка раз в секунду 
  
0B00000101//Две короткие вспышки раз в секунду  
  
0B00010101//Три короткие вспышки раз в секунду
  
0B01010101  //Частые короткие вспышки (4 раза в секунду) 
};

uint32_t msms1 0
uint8_t  blink_loop 0;
uint8_t  blink_mode 0;

//***************************************************************************************************************************************************

#include <JeeLib.h> // Low power functions library //для сна
ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup the watchdog //для сна
#include <Wire.h> // для дисплея - I2C шина
#include <LiquidCrystal_I2C.h> // библиотека для дисплея 
#include <EEPROM.h> // для использования ЕЕПРОМ
//#include <avr/wdt.h> //Чтобы использовать функции Watchdog нужно подключить к проекту стандартную библиотеку ( https://geektimes.ru/post/255800/ )
char     strokaI[32] = "                ";// Массив для вывода 1 строки на дисплей , объявляем длиннее(32символа), чтобы не было глюков с отображением на экране
char    strokaII[32] = "                ";// Массив для вывода 2 строки на дисплей

// ЭТО нужно для вывода на 128*64 Adafruit_SSD1306 дисплей
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display2(OLED_RESET);
#define XPOS 0
#define YPOS 1
#define DELTAY 2
// конец настройки для вывода на 128*64 Adafruit_SSD1306 дисплей
  


//LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display для 0x27 - настройка дисплея для библиотеки LiquidCrystal_I2C2004V1
//Перед прошивкой скетча убедитесь в наличии нужных библиотек,например  d:\777\Soft\arduino\arduino-1.6.11\libraries\LiquidCrystal_I2C\   https://github.com/marcoschwartz/LiquidCrystal_I2C например

LiquidCrystal_I2C lcd(PCF8574_ADDR_A21_A11_A014561611121314POSITIVE);  // для newE  описание библиотеки http://elchupanibrei.livejournal.com/27443.html#t23347

float UakbONorOFF 12.1//  напряжение порога сработки акб
float U_acc_real 0;     //  реальное напряжение +ACC на входе делителя 
float U_akb_real 0;     //  реальное напряжение +30 на входе делителя 
int Uacc 0;             // напряжение с делителя ACC 0-1024 
int Uakb 0;             // напряжение с делителя АКБ 0-1024    

//PORTB
const byte SAMOZAPITKA_Pin                    9;   // номер пина самозапитки блока
const byte LED_Pin                            13;  // номер пина встроенного светодиода индикации 
const byte OTG_Pin                            10;  // номер пина управляющего микросхемой, управляющей режимом OTG
const byte HUB_Pin                            11;  // номер пина управляющего транзистором, управляющего Питанием ХАБа
const byte SLEEP_Pin                          12;  // номер пина управляющего микросхемой, которая даёт массу на пин сна ( датчик холла)
 
//PORTD
const byte PlanshBAT_Pin                      6;  // номер пина управляющего микросхемой, управляющей питанием БАТАРЕЕЙ планшета (через управляющую ногу IN2-5pin )0 = нет питания; 1 = есть питание ( БАТАРЕИ планшета)
const byte REGISTRATOR_Pin                    4;  // номер пина управляющего микросхемой управляющей питанием видеорегистратора
const byte FIVE_Volt_OUT_na_POGO_or_USB_Pin   2;  // номер пина управляющего сном 2 преобразователя DC-DC (+5В)
const byte REM_Pin                            7;  // номер пина управляющего транзистором, управляющего Питанием ХАБа
 
 
//логические состояния блока питания (какая ножка какой сигнал должна выдавать)
    
uint8_t  PORTBregistr 0;               // Если у нас есть 8-битная переменная PORTBregistr, то мы можем присвоить её значение регистру PORTx, и тем самым установить ножки микроконтроллера в состояние, соответствующее значению переменной PORTBregistr
boolean SAMOZAPITKA 0;                     // byte SAMOZAPITKApin = 9; /*управление самозапиткой блока питания IN4*///1 = есть самозапитка; 0 = нет самозапитки
boolean LED 0;                             // Светодиод 1 = светит; 0 = не светит
boolean SLEEP=0;                             //byte SLEEPpin = ; //1 = потух экран(есть масса на пине сна); 0 = штатная работа планшета (нет массы на пине сна) ( также 0 означает ненажатую кнопку питания, если мы используем канал ДХ для управления кнопкой питания планшета.)
boolean HUB 0;                             //byte HUBpin = 11;  0-хаб вЫключен, 1 - хаб включен
boolean OTG 0;                             //byte OTGpin = ; //1 = есть масса на OTG; 0 = нет массы на OTG

    
uint8_t  PORTDregistr 0;               //  8-битная переменная PORTDregistr
boolean PlanshBAT 0;                       //byte PlanshBATpin = 6; /* 10pin = PD6 = pin D6 PWM            ..... управление питания БАТАРЕИ планшета через управляющую ногу IN2-5pin*/ //0 = нет питания; 1 = есть питание ( БАТАРЕИ планшета)
boolean REGISTRATOR 0;                     //byte REGISTRATORpin = 4; /* 2 pin = PD4 = pin D4 выход 12В для работы видеорегистратора (D4 -IN1)*/ 
boolean FIVE_Volt_OUT_na_POGO_or_USB 0;    //byte FIVE_Volt_OUT_na_POGO_or_USBpin = 2;   32pin = PD2 = pin D2         включить управление SS2 выходом питания  +5V  на пого пин(или USB), чтоб планшет думал, что идет зарядка //0 = нет 5V на POGO; 1 = есть 5V на POGO
boolean REM 0;                             //byte REMpin = 7;           11pin = PD7 = pin D7 выход сигнала REM (+12v) (IN3) //0 = нет 12В на выходе REM; 1 = есть 12В на выходе REM
 
int PINrawACC A0;   // замер для 5й версии
int PINrawAKB A1;   // замер для 5й версии
int PINkalibrovki A2// замер для 5й версии

//int PINrawACC = A7;   // замер для 7й версии
//int PINrawAKB = A8;   // замер для 7й версии
//int PINkalibrovki = A3; // замер для 7й версии
 
//пины состояния ITS
byte STATEpinI 1;        /*логический вход для отслеживания аварийной ситуации ITS716G(724G)(питание KIW3312s-out2 и регистратор-out1) 0 = авария*/
byte STATEpinII 1;       /*логический вход для отслеживания аварийной ситуации ITS716G(724G)(выход REM-out3 и самозапитка БП-out4 )1 = авар. сит.*/

/*логические переменные, используемые в коде*/

byte flagACC 0;          /*признак включенного зажигания*/
byte flagAKB 0;             /* признак заряженной батареи*/
byte flagREM 0;             /* признак включенного выхода на усилитель звука (REM) 0 1 2*/
byte kalibrovkaNOW 0// признак того, что сейчас происходит калибровка встроенного вольтметра по АСС и АКБ.
byte kalibrovkaACC =  EEPROM.read(0);  // значение для калибровки для делителя АСС
byte kalibrovkaAKB =  EEPROM.read(1); // значение для калибровки для делителя АКБ
byte razreszenie_raboty_I_dva_C_sziny  0// Разрешили ли мы работать (инициализировали ли) I2C устройствам (дисплеи, звуковой  процессор) в текущем цикле. 1 - инициализировали и разрешили, 0 - НЕ инициализировали и запретили       
byte flagHALL 0;         //флаг отработки морга экрана при холодном старте( flagHALL = 1 экран можно включать и выключать, датчик холла на планшете инициализировался)
byte STARTUEM 0;         //Стартует ли авто ( крутим ли стартером) 0- не крутим, 1 - крутим.

//Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
// Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
//  Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И  
//   Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
   

const boolean reset_HUB_on_power_on 1;      // передёргивать ли хаб при каждом включении зажигания, для решения проблемы с определением изикапа (STK1160) 1 - после ВКЛ АСС включить хаб, выключить на 0,5с и включить опять. 0 - просто включить хаб.
const boolean power_off_HUB_on_starting 1;  // выключать ли питание на хаб при старте авто ( 1- да, выключать)
const boolean power_off_OTG_on_starting 1;  // выключать ли массу на OTG при старте авто   ( 1- да, выключать)
const boolean HALL_as_power_Switch 0;       // 0 - используем ДХ как обычно. 1 - вместо ДХ подключаем кнопку питания планшета. Если подключено как КНОПКА, то задержка перед нажатием "кнопки" после включения АСС это SLEEP_timer_pri_vkl_ACC, а после вЫключения  SLEEP_timer_pri_vykl_ACC. Удержание нажатия = 0,5с. 

//НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________
  
float Uperezariadki 15.5;              // напряжение, выше которого будет считаться, что идёт перезарядка аккумулятора авто.
  
float UrabotyREM 11.8;                 // напряжение, выше которого будет работать усилитель звука, если акб не садился.
  
float UnevykluczeniaREM 13.7;          // напряжение, когда машина считается заведённой. Тогда, если завели машину, ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
  
float Uakb_Kogda_ACC_vYkluczeno 11.9;  // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вЫключенном АСС
  
float Uakb_Kogda_ACC_vkluczeno 11.1;   // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вКлюченном АСС
  
float UaccONorOFF 10.1;                // напряжение порога сработки асс.  Т.е. если на пин блока питания "вход АСС" подать ниже UaccONorOFF (11,1), то зажигание будет считаться выключенным.
//КОНЕЦ НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________
  
/*счётчики времени*/
  //НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!
  
 
const unsigned long timeUntilBATOff 345600000;                     // время до выключения питания на батарею планшета после выключения зажигания., считаем ОТ момента выключения зажигания. если прошло 48 часов, как выключили ACC // пауза  (3600000 - 60мин) (60000 - 1 мин)(10800000=3ч) (1800000=5ч)
 
const unsigned long timeUntilALLOff 172800000 timeUntilBATOff;   // время до полного выключение блока,  после выключения зажигания (ACC)и уже после того, как выключится питание на батарею планшета    ) (2суток = 172800000)) (4суток = 345600000)
 
unsigned long timeBeforeRemOff 1800000;                            // 1800000=30мин. Время, оставшееся до отключения выхода REM после включения зажигания и незаводки машины. ( то есть сколько времени будет включён усилитель звука, если заглушить машину и просто слушать музыку,  при нормальном АКБ)

 
unsigned long timeAfterACC_starting 7000;                // не может быть меньше REM_timer_pri_vykl_ACC! //задержка перед началом процедуры выключения зажигания во время кручения стартером
 
unsigned long timeAfterACC_accOFF 2000;                  // не может быть меньше REM_timer_pri_vykl_ACC! //задержка перед началом процедуры выключения зажигания во время обычного выключения зажигания
 
unsigned long timeWhileAkbLow 40000;                     // 40000 время, через которое начнётся полное выключение блока когда напряжение на АКБ очень низкое.   /* если севший аккумулятор //через 40с вЫключаем питание на батарею планшета и вырубаем сам БП.*/
 
unsigned long pauseTimeHALL 140000;            // Для первого включения планшета. Раньше этого времени экран не будет тухнуть! Время паузы перед морганием-тушением экрана (для датчика холла)(равен времени загрузки планшета плюс секунд 10-20)= 2мин
 
unsigned long vremia_obnovlenia_displeya 250;  // Время, через которое будет обновляться информация на дисплей I2C  (время обновления I2C дисплея)

//тут настраиваем паузу при вКлючении зажигания ( АСС) и по истечении этого времени активируем/деактивируем  
//соответствующий пин блока питания (время независимо друг от друга)
const unsigned long  PlanshBAT_timer_pri_vkl_ACC 1100;// пауза  после включения ACC перед включением питания на батарею планшета
const unsigned long  FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC 1400;// пауза  после включения ACC перед включением +5V (POGO(USB) выхода для пина зарядки планшета (+5В пого или ЮСБ) 
const unsigned long  OTG_timer_pri_vkl_ACC 50;// пауза  после включения ACC перед включением минуса на OTG ( 4й контакт ЮСБ разъема на планшете)  (включается определение ЮСБ перифирии планшетом.)
const unsigned long  HUB_timer_pri_vkl_ACC 2100;// пауза  после включения ACC перед подачей питания на хаб. Значение должно быть больше либо равно FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC.
const unsigned long  REGISTRATOR_timer_pri_vkl_ACC 2500;// пауза  после включения ACC перед включением  питания +12В на видеорегистратор
const unsigned long  REM_timer_pri_vkl_ACC 2500;// пауза  после включения ACC перед включением  питания +12В на REM (включение усилителя звука)
const unsigned long  SLEEP_timer_pri_vkl_ACC 3000// пауза  после включения ACC перед включением экрана планшета (масса на Датчик Холла)
const unsigned long  I_dva_C_szina_ON_time 150;        //Время, через которое I2C шина включится после вКлючения зажигания - начнётся передача по шине I2C.

//тут настраиваем паузу при вЫключении зажигания ( АСС) и по истечении этого времени активируем/деактивируем 
//соответствующий пин блока питания (время независимо друг от друга)
const unsigned long  OTG_timer_pri_vykl_ACC 2500// пауза  после вЫключения ACC перед вЫключением минуса на OTG ( 4й контакт ЮСБ разъема на планшете) (вЫключается определение ЮСБ перифирии планшетом.)
const unsigned long  FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC 5000// пауза  после вЫключения ACC перед вЫключением +5V (POGO(USB) выхода для пина зарядки планшета (+5В пого или ЮСБ) 
const unsigned long  HUB_timer_pri_vykl_ACC 5000// пауза после вЫключения ACC перед убиранием питания с хаба. Значение должно быть меньше либо равно FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC.
const unsigned long  SLEEP_timer_pri_vykl_ACC 0// пауза  после вЫключения ACC перед вЫключением экрана планшета (масса на Датчик Холла)
const unsigned long  REM_timer_pri_vykl_ACC 1000;// не может быть больше timeAfterACC_accOFF и timeAfterACC_starting!  Пауза  после вЫключения ACC перед вЫключением  питания +12В на REM (вЫключение усилителя звука), тут 1000 это на сколько раньше выключать выход REM перед остальными выключениями
const unsigned long  lcd_noBacklight_timer_pri_vykl_ACC 17000// 7000 пауза после вЫключения ACC перед убиранием подсветки I2C LSD дисплея (1602)
const unsigned long  I_dva_C_szina_OFF_time lcd_noBacklight_timer_pri_vykl_ACC 3000;      //Время, которое I2C шина работает после вЫключения зажигания, потом  - закончится передача по шине I2C.

 //конец настроек таймингов.__________________________________________________________________________________________


//К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
// К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
//  К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И  
//   К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
   





int vremia_sna_ATMEGI 100//   sleep for XXX seconds   - когда запретили работу I2C шины, запускаем сон каждый цикл(loop) на 0,1 сек. (0-200) Нужно для режима энергосбережения атмеги.                                                                                         
unsigned long eventTime 0;
unsigned long pauseTimeACC millis();      // сброс времени для отсчета отключения самозапитки
unsigned long pauseTimeAKB millis();
unsigned long pauseDisplay 0;             /* таймер для обновления информации на дисплее, чтобы не мерцал*/
unsigned long timeAfterACC 5000;          /*базовое (для инициализации) , ни на что не влияет.  Меняйте   timeAfterACC_accOFF и timeAfterACC_starting   !        время после выключения зажигания, после истечения которого вырубается экран, хаб, otg-режим*/
unsigned long TimerREM 0;                 /*базовое (для инициализации) , ни на что не влияет.  Отсчет до выключения выхода REM при заглушенном авто и включенном зажигании.3600000 = час */
unsigned long TIMER millis();             /*базовое (для инициализации) , ни на что не влияет. */
unsigned long H = (millis()/3600000); // часы 
byte M = ((millis()-(H*3600000))/60000); //минуты
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================




void UPRAVLENIE_PINAMI() // функция перевода логических параметров в реальные состояния пинов   // http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry  // https://geektimes.ru/post/255744/ Ускоряем свою Arduino   /* http://robotosha.ru/arduino/digitalwrite-optimizing-arduino.html */
{// UPRAVLENIE_PINAMI ~~~//тут мы сначала пишем  в переменную регистры, а потом сделаем PORTB = PORTBregistr; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
// PORTBregistr - обрабатывем регистры порта B атмеги

/*        if (LED == 1 ){ PORTBregistr |= 1<<5;     } //PORTB |= 1<<5; //установит "1" (сигнал высокого уровня) на выводе PB5. //digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
             else { PORTBregistr &= ~(1<<5);  } //PORTB &= ~(1<<5); //установит "0" (сигнал низкого уровня) на выводе PB5. //digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
     if (SAMOZAPITKA == 1){ PORTBregistr |= (1 << 1); } else {PORTBregistr &= ~((1 << 1));}         //PB1 управление самозапиткой блока питания IN4///1 = есть самозапитка; 0 = нет самозапитки //http://microsin.net/programming/avr/accessing-avr-ports-with-winavr-gcc.html
             if (OTG == 1){ PORTBregistr |= (1 << 2); } else {PORTBregistr &= ~((1 << 2));}         //byte SLEEPpin = 10;  PB2  управление транзюком сна VT4 (на датчик холла)) //1 = потух экран(есть масса на пине сна); 0 = штатная работа планшета (нет массы на пине сна)
           if (HUB == 0)  { PORTBregistr |= (1 << 3); } else {PORTBregistr &= ~((1 << 3));}         //HUB =0;//byte HUBpin = 11;  PB3 управление транзюком питания хаба // 1-есть питание, 0 - нет питания
         if (SLEEP == 0)  { PORTBregistr |= (1 << 4); } else {PORTBregistr &= ~((1 << 4));}         //bool OTG = 0; //byte OTGpin = 12; /* 16pin = PB4 = pin D12 MISO управление транзюком OTG Q1 //1 = есть масса на OTG; 0 = нет массы на OTG
*/
      
digitalWrite(LED_PinLED);                   //управление встроенным светодиодом
      
digitalWrite(SAMOZAPITKA_PinSAMOZAPITKA);   // управление самозапиткой блока питания 1 = есть самозапитка; 0 = нет самозапитки //http://microsin.net/programming/avr/accessing-avr-ports-with-winavr-gcc.html
      
digitalWrite(OTG_PinOTG);                   // управление OTG    
      
digitalWrite(HUB_Pin, !HUB);                  // управление транзистором питания хаба // 1-есть питание, 0 - нет питания
      
digitalWrite(SLEEP_Pin, !SLEEP);               // управление микросхемой, которая даёт массу на пин сна ( датчик холла)
    
     
// PORTDregistr - обрабатывем регистры порта D атмеги
//PORTD

 
digitalWrite(PlanshBAT_PinPlanshBAT);        //управление питанием БАТАРЕЕЙ планшета (+4,0)
 
digitalWrite(REGISTRATOR_PinREGISTRATOR);    //управление питанием видеорегистратора (+12)
 
digitalWrite(FIVE_Volt_OUT_na_POGO_or_USB_PinFIVE_Volt_OUT_na_POGO_or_USB);   //управление вторым преобразователем DC-DC (+5В)
 
digitalWrite(REM_PinREM);                    //управление выходом REM (+12)
 
 
//       if (PlanshBAT == 1){ PORTDregistr |= (1 << 6); } else {PORTDregistr &= ~((1 << 6));}         //bool PlanshBAT = 0; //byte PlanshBATpin = 6;  10pin = PD6 = pin D6 PWM    включить 1 канал KIW            ..... управление питания БАТАРЕИ планшета через управляющую ногу IN2-5pin //0 = нет питания; 1 = есть питание ( БАТАРЕИ планшета)
     
if (REGISTRATOR == 1){ PORTDregistr |= (<< 4); } else {PORTDregistr &= ~((<< 4));}         //bool REGISTRATOR = 0;   //byte REGISTRATORpin = 4;  2 pin = PD4 = pin D4 выход 12В для работы видеорегистратора (D4 -IN1)
 
if (FIVE_Volt_OUT_na_POGO_or_USB == 1){ PORTDregistr |= (<< 2); } else {PORTDregistr &= ~((<< 2));}         //bool FIVE_Volt_OUT_na_POGO_or_USB = 0;   //byte FIVE_Volt_OUT_na_POGO_or_USBpin = 2;   32pin = PD2 = pin D2         включить 2 канал KIW    управление SS2 выходом питания  +5V (2 канал kiw3312s) на пого пин(или USB), чтоб планшет думал, что идет зарядка //0 = нет 5V на POGO; 1 = есть 5V на POGO
             
if (REM == 1){ PORTDregistr |= (<< 7); } else {PORTDregistr &= ~((<< 7));}         //bool REM = 0; //byte REMpin = 7;           11pin = PD7 = pin D7 выход сигнала REM (+12v) (IN3) //0 = нет 12В на выходе REM; 1 = есть 12В на выходе REM

           // Serial.print ("PORTB, BIN = "  ); Serial.println (PORTB, BIN); // вывели порт B атмеги на монитор порта
           // Serial.print ("PORTDregistr, BIN = "  ); Serial.println (PORTDregistr, BIN); // вывели порт D атмеги на монитор порта
           // Serial.print ("SAMOZAPITKA = "  ); Serial.println (SAMOZAPITKA);
//PORTD = PORTDregistr; //прописали порту D атмеги в регистры команду на запись нулей и единиц.
//PORTB = PORTBregistr; //прописали порту B атмеги в регистры команду на запись нулей и единиц.
}//конец UPRAVLENIE_PINAMI ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 



void setup() //настройки
{

 
  

  
Serial.begin(115200);

if( 
kalibrovkaACC == 255 ){kalibrovkaACC=127;} // проверяем , прописана ни калибровка в еепром, если нет( 255), то берём значения по умолчанию  
if( kalibrovkaAKB == 255 ){kalibrovkaAKB=127;} // проверяем , прописана ни калибровка в еепром, если нет( 255), то берём значения по умолчанию  =127

// настройки портов  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~   
 
DDRD 0b11010100;  //работает!!
 
DDRB 0b00111110;  //работает!!
 
pinMode(PINkalibrovkiINPUT);  // пин калибровки
 
digitalWrite(PINkalibrovki1); // подтяжка +5 пина калибровки
// конец настроек портов  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 

//настройки состояний при подаче питания на БП ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 
  
PlanshBAT 0;          //digitalWrite(PlanshBATpin, 0);  //вЫключаем питание на батарею планшета
  
SAMOZAPITKA 0;        // digitalWrite(SAMOZAPITKApin, 0);  //выключаем SAMOZAPITKApin, при этом пропадает управление на IN4, система ПОЛНОСТЬЮ обесточивается
  
OTG 0;                //digitalWrite(OTGpin, 0); //вЫключаем минус на OTG (8 pin PW1)
  
FIVE_Volt_OUT_na_POGO_or_USB 0;    //digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 0); //вЫключаем +5V (POGO(USB))
  
HUB 0;                //digitalWrite(HUBpin, 1); // подаем + на управляющий транзюк хаба, тот закрывается и не пускает +5В с KIW (2вых)на хаб = ВЫключаем хаб
  
REM 0;                //digitalWrite(REMpin, 0); // // выключаем выход REM
  
REGISTRATOR 0;        //digitalWrite(REGISTRATORpin, 0); // выключаем питание  на видеорегистратор
//  wdt_enable (WDTO_2S);   // Запуск таймера watchdog:   Для тестов не рекомендуется устанавливать значение менее 8 сек. Таймер будет считать ровно столько, сколько указано в константе. По истечении этого времени произойдет перезагрузка. /* Возможные значения для константы WDTO_15MS WDTO_30MS WDTO_60MS WDTO_120MS WDTO_250MS WDTO_500MS WDTO_1S WDTO_2S WDTO_4S WDTO_8S 2 s   (WDTO_2S  ATMega 8, 168, 328, 1280, 2560) (   wdt_enable (WDTO_8S);) https://geektimes.ru/post/255800/ https://tushev.org/articles/arduino/5/arduino-and-watchdog-timer     
 //UPRAVLENIE_PINAMI();     //сделать пллавный пуск - определить нужное состояние пинов без их предварительного дергания --- настроили логику и отдали её в функцию UPRAVLENIE_PINAMI. 
 //конец настроек состояний при подаче питания на БП~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 
}
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================

void displayDataToDISPLAY()//>>>>>>>>>>>>>> Сформировали строки, теперь надо их вывести на дисплеи:>>>>>>>>>>>>>> 
{//void displayDataToDISPLAY()
//вывод на 2хстрочный дисплей LCM 1602 с I2C ( на базе расширителя портов PCF8574)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    //Serial.print("strokaI  = "); Serial.println(strokaI);  // раскомментить для вывода информации в ком порт для отладки
    
lcd.setCursor(00);
    
lcd.print(strokaI);
  
    
//Serial.print("strokaII = "); Serial.println(strokaII); // раскомментить для вывода информации в ком порт для отладки
    
lcd.setCursor(01); //2строка 0символ 
    
lcd.print(strokaII);


    
//вывод на 128*64 дисплей (Adafruit_SSD1306) первой строки
                                                        
                                                          
display2.clearDisplay();        // очистили буфер 
                                                          
display2.setTextSize(1);        // установили размер текста (1-4)
                                                          
display2.setCursor(0,0);        // начальная точка вывода
                                                          
display2.println(strokaI);      // скинули значение I строки в буфер 128*64 дисплея
    //вывод на 128*64 дисплей (Adafruit_SSD1306) второй строки
                                                          
display2.println(strokaII);     // скинули значение II строки в буфер 128*64 дисплея
            
if ( ((millis() - pauseTimeACC) >=  (5000+timeAfterACC)) && (flagACC==0) )    // после 5 сек после выключения зажигания буфер будет чиститься перед выводом, соответственно на 128*64 Adafruit_SSD1306 дисплей выводиться ничего не будет Это нужно для того, чтобы ночью экран не светился ( так как пиксели активные и дают свет без подсветки) 
                                                          
{
                                                          
display2.clearDisplay();        // очистили буфер           
                                                          

                                                          
display2.display();             //эта строка выводит картинку 1306 из буфера на экран!
//Вывод строк окончен.______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
      
}//void displayDataToDISPLAY()
void IntToCharI(int numchar *text)//функция, возвращающая число в текстовый вид 0 1
{
  
//text[0] = (num/100) + '0'; // первое значение _00 - эта строчка нужна для 3хзначного числа.
  //text[1] = ((num/10)%10) + '0';// второе значение __0
  
text[2] = (num%10) + '0'// третее значение ___
 
}

void IntToCharII(int numchar *text)//функция, возвращающая число в текстовый вид 00 11
{
  
//text[0] = (num/100) + '0'; // первое значение _00 - эта строчка нужна для 3хзначного числа.
  
text[0] = ((num/10)%10) + '0';// второе значение __0
  
text[1] = (num%10) + '0'// третее значение ___
 
}


void IntToCharIII(int numchar *text)//функция, возвращающая число в текстовый вид 00 11
{
  
text[0] = (num/100) + '0'// первое значение _00 - эта строчка нужна для 3хзначного числа.
  
text[1] = ((num/10)%10) + '0';// второе значение __0
  
text[2] = (num%10) + '0'// третее значение ___
}
  
void IntToCharIIII(int numchar *text)//функция, возвращающая число в текстовый вид 0000 1111
{
 
text[0] = (num/1000) + '0';//0 знач
 
text[1] = (num/100)%10 '0'// первое значение _00 - эта строчка нужна для 3хзначного числа.
 
text[2] = ((num/10)%10) + '0';// второе значение __0
 
text[3] = (num%10) + '0'// третее значение ___
}
void FloatToCharIIIII(float numchar *text)//функция, возвращающая число в текстовый вид 00.00 11.11
{

  
int Int num*100;
 
text[0] = (Int/1000) + '0';//0 знач   7896
 
text[1] = (Int/100)%10 '0'// первое значение _00 - эта строчка нужна для 3хзначного числа.
 
text[2] =  '.';
 
text[3] = ((Int/10)%10) + '0';// второе значение __0
 
text[4] = (Int%10) + '0'// третее значение ___
}


void printDISPLAY() //функция формирования информации на дисплей ( точнее на два: 128*64 и 1602)
{
//_____________________________________________ФОРМИРУЕМ СООБЩЕНИЕ НА LCD ДИСПЛЕЙ____________________________________________________________

 
= (millis()/3600000);
 
= ((millis()-(H*3600000))/60000); 
//int S = (((millis()/1000)-(H*3600))- (M*60));
//if ((((millis())-(H*3600000))- (M*60000)) < 200 ){lcd.clear(); }//очистка дисплея
//int M = (millis()/60000); //минуты

 
if (flagACC == 1){lcd.backlight();}// для newE и для 0x27  
 // в 256 строке выключение подсветки LCD дисплея

 
 
 //пример: sprintf( strokaII,"SETUP volume on ");

//обработка 1й строки_________AKB ACC REM_____________________________________________________________________________________________________________________________________________________________________
 
sprintf(strokaI,"                ") ; 
                  
//IntToCharIIII((millis()/60000), &strokaI[0]); // вывод минут 0000 4 цифры СЕКУНД // если превысит 9999, то будут кроказябры!!! вида  ;0129
                  
IntToCharIII(H, &strokaI[0]);  // вывод часов 000 
                   
strokaI[3] =  ':'// вывод двоеточия 
                    
IntToCharII(M, &strokaI[4]);  // вывод минут 00 
                       
strokaI[7]= flagAKB '0';// вывод флага AKB 5 символ
                        
strokaI[8]= flagACC'0';// вывод флага AСС 6 символ
                         
strokaI[9]= REM '0';// вывод  rem 7 символ 1-усилок включен, 0 - выключен
                          
strokaI[10]= flagREM '0';// вывод  флага!!! rem 7 символ 1-усилок включен, 0,2 - выключен
                          
FloatToCharIIIII (U_acc_real,  &strokaI[11]);  // вывод напряжения АСС 
//конец обработки 1й строки ______________________________________________________________________________________________________________________________________________________________________________

//обработка 2й строки______________________________________________________________________________________________________________________________________________________________________________
 
TIMER = (  pauseTimeAKB  timeUntilALLOff millis()  )/60000// вывод кол-ва минут, оставшиеся до вЫключения блока (когда выключено АСС)


  // _______________________________Первые 30с после вкл -выкл ACC выводим версию блока.____________________________________________________________________________________________________________________________________________________
  
if (    ( millis()-pauseTimeACC  30000 )&& flagACC == 1   ){  sprintf(strokaII,"m__             ") ; IntToCharII(ver, &strokaII[1]);} else {  sprintf(strokaII,"____            ");   IntToCharIIII(TIMER, &strokaII[0]); } //Первые 30с после вкл -выкл ACC выводим версию блока
  // _____________________________________________________________________________________________________________________________________________________________________________________________________________________________________
 


//вывод OTG HUB POGO HALL
                      
strokaII[5]= STARTUEM '0';// 
                       
strokaII[6]= OTG '0';// вывод флага OTG 5 символ
                        
strokaII[7]= HUB '0';// вывод флага HUB 6 символ
                         
strokaII[8]= FIVE_Volt_OUT_na_POGO_or_USB '0';// вывод флага FIVE_Volt_OUT_na_POGO_or_USB (ПРИЗНАК ЗАРЯДКИ) 7 символ 
                           
strokaII[9]= !SLEEP '0';// вывод флага flagHALL 8 символ (инверсно)  1-экран включен, 0 - выключен
                               
FloatToCharIIIII (U_akb_real,  &strokaII[11]); // вывод напряжения АКБ
//конец обработки 2й строки ______________________________________________________________________________________________________________________________________________________________________________

if (kalibrovkaNOW >= && kalibrovkaNOW 255 )// если активен режим калибровки, то выводим данные для калибровки.
                      
{
                       
sprintf (strokaI,"                ") ; 
                       
IntToCharIII(Uacc,  &strokaI[0]);
                       
IntToCharIII(Uakb,  &strokaI[4]);
                       
IntToCharIII(kalibrovkaNOW, &strokaI[7]);  // вывод РЕЖИМА калибровки 
                       
                       
sprintf(strokaII,"c               ") ;
                       
IntToCharIII(kalibrovkaACC, &strokaII[1]);  // вывод значения калибровки АСС 
                       
IntToCharIII(kalibrovkaAKB, &strokaII[5]);  // вывод значения калибровки АСС 
                       
                       
FloatToCharIIIII (U_acc_real,  &strokaI[11]); // вывод напряжения АКБ
                       
FloatToCharIIIII (U_akb_real,  &strokaII[11]); // вывод напряжения АКБ

                      
}

//Вывод строк.______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
 
 
displayDataToDISPLAY(); //>>>>>>>>>>>>>> Сформировали строки, теперь надо их вывести на дисплеи:>>>>>>>>>>>>>> 
  



  /* так выглядит индикация на дисплее
  
   ================
  |000:00 111  0.000|          1 строка   *   вывод времени работы блока H:M                 *         AKB ACC REM            *    вывод напряжения АСС
  |2616  1110  14.50|    
   ================           2 строка   *   кол-во минут, оставшиеся до выключения блока    *         OTG HUB POGO HALL      *    вывод напряжения АКБ    
                                                                                               

*/
}

 
/******************************************конец индикации светодиодом и  вывода на дисплей********************************************************************************************************************************************************************************/
                                    

//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================

void analogReadU (byte averageFactor//функция усреднённого чтения аналоговых входов (A0 A1)
{//void analogReadU
  
int newUacc analogRead(PINrawACC);
  
int newUakb analogRead(PINrawAKB); 
 
   if (
averageFactor 0)        // усреднение показаний для устранения "скачков"
  
{      
    
Uacc = (Uacc * (averageFactor 1) + newUacc) / averageFactor;  
    
Uakb = (Uakb * (averageFactor 1) + newUakb) / averageFactor;  
    
// <новое среднее> = (<старое среднее>*4 + <текущее значение>) / 5 я тут немного поправил
  
} else {
    
Uakb=newUakb// не делаем усреднений, что прочитали то и считаем выводом
    
Uacc=newUacc// не делаем усреднений, что прочитали то и считаем выводом
  
}


}
//void analogReadU

void rejim_kalibrovki() //функция измерения, калибровки и записи полученных значений в еепром
{//void rejim_kalibrovki()
  
lcd.noBacklight();
  
delay (50);
  
lcd.backlight();
  
delay (250);
   if (
digitalRead(PINkalibrovki)== && kalibrovkaNOW 6)  {kalibrovkaNOW ++;} 
   else 
// тут достигли 6 касаний точки калибровки и ЗАПУСКАЕМ НЕПОСРЕДСТВЕННО ПРОЦЕСС КАЛИБРОВКИ ( ДЛЯ ЭТОГО ПОДАЁМ РОВНО 12,00В НА БЛОК ПИТАНИЯ ( асс и акб)
  
//else 
    
if (kalibrovkaNOW >= 6)
    {
//if (kalibrovkaNOW >= 6)
      
PORTBregistr 0// выключили всё
      
PORTDregistr 0// выключили всё 
      
UPRAVLENIE_PINAMI(); // сказали регистрам исполнить  " выключили всё ", вызвав функцию
      
delay (600); // для зарядки кондёров после снятия нагрузки
      
analogReadU (10); //вызов функции усреднённого чтения аналоговых входов - прочитали сырые данные с АЦП A0 и А1, потом их усреднили(10)раз
      
kalibrovkaACC 1200000/Uacc-1410// вычисляем значение калибровки, подав 12В на вход делителя U ( просто подключив питание к блоку питания)
      
kalibrovkaAKB 1200000/Uakb-1410// вычисляем значение калибровки, подав 12В на вход делителя U ( просто подключив питание к блоку питания) 
      
{kalibrovkaNOW ++;} 
    }
//if (kalibrovkaNOW >= 6)
  
}//else 
if ( kalibrovkaNOW == 15 &&  digitalRead(PINkalibrovki)== 0)   //по достижению счета в 254 и ПРИ МАССЕ НА ПИНЕ КАЛИБРОВКИ данные калибровки запишутся в еепром
                    
{
                      
kalibrovkaNOW 255;
                     
EEPROM.write(0,kalibrovkaACC);
                     
EEPROM.write(1,kalibrovkaAKB);
                      
                       
sprintf (strokaI,"end KALIBR.     ") ; 
                       
sprintf(strokaII,"c               ") ;
                       
IntToCharIII(kalibrovkaACC, &strokaII[1]);  // вывод значения калибровки АСС 
                       
IntToCharIII(kalibrovkaAKB, &strokaII[5]);  // вывод значения калибровки АСС 
                       
                       
FloatToCharIIIII (U_acc_real,  &strokaI[11]); // вывод напряжения АКБ
                       
FloatToCharIIIII (U_akb_real,  &strokaII[11]); // вывод напряжения АКБ
                      
displayDataToDISPLAY(); // 
                     
delay (10000);
                    
                     
                    }

}
//void rejim_kalibrovki()




void STATUS_REM() 
{
//void STATUS_REM() 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~обработка статуса выхода REM~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*если напруга батареи больше 12В, то включаем еще и усилитель звука (выход REM) /но включаем его только на  timeBeforeRemOff (30 минут), если не заведены.*/

    
if (U_akb_real >= UrabotyREM && flagACC == && flagREM == 0  ) {flagREM 1TimerREM millis();} //если подзаряжен акб и включили зажигание  - ВКЛЮЧАЕМ REM
    
if (U_akb_real >= UrabotyREM && flagACC == && ( millis() - TimerREM >= timeBeforeRemOff )) {flagREM ;}  //  если кончилось время обратного отсчета - статус рем - 2.
     //if (U_akb_real >= UnevykluczeniaREM && flagACC == 1){ (flagREM = 1);TimerREM = millis();} // если завели машину, - ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
    
if (U_akb_real >= UrabotyREM && flagREM == && flagACC == 0){ flagREM 0;} // если восстановилось напряжение при выключенном зажигании - обнуляем статус РЕМ.
    
if (U_akb_real <= UrabotyREM && flagACC == 1){ flagREM 2;} //если подсел акб при включенном зажигании - статус рем - 2.
      
if (U_akb_real >= UnevykluczeniaREM && flagACC == ){ (flagREM 1);TimerREM millis();} // если завели машину, - ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
       
if (U_akb_real >= UnevykluczeniaREM &&  flagREM == 3){ (flagREM 1);TimerREM millis();} // если завели машину, - ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
    
if (U_akb_real >= Uperezariadki){flagREM 2;}// проверка на перезаряд
    
if( flagREM == ||  flagREM == 2){REM 0;}  // выключаем выход REM
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~конец отработки выхода REM~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
}//void STATUS_REM() 


void obrabotka_ACC_ON() 
//START void obrabotka_ACC_ON() 
 //  ------------========================== блок ACC ========================-----------------------------------------------------------------------------


  //             -----------------=========ВКЛЮЧИЛИ ЗАЖИГАНИЕ=============---------------- 
  
if ((Uperezariadki U_acc_real) && (U_acc_real >= UaccONorOFF) && flagACC == && flagAKB == //проверка напруги АСС и АКБ при флаге ACC = 0
  
{
    
flagACC 1;
    
pauseTimeACC millis();
    
pauseTimeAKB millis();
    
  }

if (
U_acc_real >= UaccONorOFF)  //как только включили зажигание ( при любом напряжении батареи)


 if (
millis() - pauseTimeACC >= I_dva_C_szina_ON_time /* пауза XXX=I_dva_C_szina_ON_timec после появления напряжения на ACC и потом делать следующ(пока включено ACC):*/
        
{
            if (
razreszenie_raboty_I_dva_C_sziny  == 0// переопрашиваем дисплеи I2C и ставим флаг, чтобы они работали. 
      

             
//lcd.clear(); //очистка дисплея не нужна со строковым выводом
               
lcd.begin(162); //инициализация дисплея 1602 для newE библиотеки
         
sprintf(strokaI,"    INIT OK     ") ;
         
lcd.setCursor(00);
               
lcd.print(strokaI);
               
display2.begin(SSD1306_SWITCHCAPVCC0x3C);  // display 2 or adres 0x3D для 1306 дисплея
               
display2.clearDisplay();        // для 1306 дисплея
               
display2.setTextColor(WHITE);   // для 1306 дисплея
      // ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ТУТ надо будет включать питание на TDA7442 ! ! ! ! ! ! ! ! ! 
      
}
      
razreszenie_raboty_I_dva_C_sziny  1// разрешаем работу шины I2C 
      
        
}
               
        
// конец как только включили зажигание ( при любом напряжении батареи)
//} не нужна скобка


if (flagACC ==)
{
// если flagACC == 1
//проверить
      
if (((millis() - pauseTimeACC) >= (20)) )
      {
      if (
flagACC==&& flagAKB==1){STARTUEM 0;}  // определяем предположительный старт авто c задержкой XXXмс
      

//проверить      
  
if (millis() - pauseTimeACC >= PlanshBAT_timer_pri_vkl_ACC /* пауза 1.1c после включения ACC и потом делать следующ(пока включено ACC):*/
        
{
         
PlanshBAT 1;        //digitalWrite(PlanshBATpin, 1);  /*включаем питание на батарею планшета  = этим подаём 12В на DC-DC. На 1м канале dc-dc сразу появляется напряжение (3,8-4,2 - как настроено)*/ 
        
}
  
  if (
millis() - pauseTimeACC >= FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
        
{
          
FIVE_Volt_OUT_na_POGO_or_USB 1;  //digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 1); /*включаем +5V (POGO(USB) нужно для распознавания планшетом признака зарядки. ( можно подавать на +5В USB кабеля (для тимуровской прошивки или если не используется датчик холла)*/
        
}
  
if (
millis() - pauseTimeACC >= OTG_timer_pri_vkl_ACC /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
       
{
         
OTG 1;              //digitalWrite(OTGpin, 1); /*включаем минус на OTG  (включается определение перифирии планшетом.)*/
       
}

if (
millis() - pauseTimeACC >= HUB_timer_pri_vkl_ACC /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
       
{
         
HUB 1;               //digitalWrite(HUBpin, 0); /*Включаем хаб = подаем минус на управляющий транзюк хаба, тот открывается и пускает +5В dc-dc (2вых)на хаб*/
       
}
                  
  if (
reset_HUB_on_power_on == 1)
  {
                  if (
millis() - pauseTimeACC >= (HUB_timer_pri_vkl_ACC+500) ) /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
                         
{
                           
HUB 0;               //digitalWrite(HUBpin, 1); /*Выключаем хаб*/
                         
}
                         
                  if (
millis() - pauseTimeACC >= (HUB_timer_pri_vkl_ACC+1000) ) /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
                         
{
                           
HUB 1;               //digitalWrite(HUBpin, 0); /*Включаем хаб = подаем минус на управляющий транзюк хаба, тот открывается и пускает +5В dc-dc (2вых)на хаб*/
                         
}
  }
       
  if (
millis() - pauseTimeACC >= REGISTRATOR_timer_pri_vkl_ACC )/*через 2,2с после включения ACC включаем:  */
        
{
          
REGISTRATOR 1;// digitalWrite(REGISTRATORpin, 1); /* включаем питание  на видеорегистратор*/
          
if (millis() < 15000)  {flagREM =0;} // в первые 15 секунд при холодном пуске держим REM выключенным
      
if( flagREM == 1  && flagAKB == ){REM 1;} /* включаем выход REM*/
        
}

 if (
millis() - pauseTimeACC >= REM_timer_pri_vkl_ACC )/*через 2,2с после включения ACC включаем:  */
        
{
         if (
millis() < 15000)  {flagREM =0;} // в первые 15 секунд при холодном пуске держим REM выключенным
         
if( flagREM == 1  && flagAKB == ){REM 1;} /* включаем выход REM*/
        
}        

if (
HALL_as_power_Switch == 0)
//if (HALL_as_power_Switch == 0)
        
if (millis() - pauseTimeACC >= SLEEP_timer_pri_vkl_ACC // пауза  после включения ACC и потом делать следующ(пока включено ACC):
        
{SLEEP 0;} //digitalWrite(SLEEPpin, 0); /*включаем экран*/
//if (HALL_as_power_Switch == 0) 

if (HALL_as_power_Switch == 1)
{
//if (HALL_as_power_Switch == 1)
    
if (millis() - pauseTimeACC >= SLEEP_timer_pri_vkl_ACC )    {SLEEP 1;}//digitalWrite(SLEEPpin, 0); /*включаем экран*/
    
if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vkl_ACC+500) ) { SLEEP 0;}
    
//if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vkl_ACC+1000) ) { SLEEP = 1;}
}//if (HALL_as_power_Switch == 1)
    
    
}// если flagACC == 1

STATUS_REM(); //зашли в функцию обработки статуса выхода REM

        
}//END void obrabotka_ACC_ON() 

void obrabotka_ACC_OFF()
//START obrabotka_ACC_OFF()
 //-----------------=========ВЫКЛЮЧИЛИ ЗАЖИГАНИЕ=============----------------
   

                                                            
  
if ((U_acc_real UaccONorOFF) && flagACC == 1)    
                                                {
                                                  
flagACC 0;  /*Выключили зажигание*/
                                                  
pauseTimeACC millis();
                                                  
pauseTimeAKB millis();
                                                }
 if (
flagACC==0)
 {
// if (flagACC==0)
  // 

  
if (((millis() - pauseTimeACC) >= (timeAfterACC-REM_timer_pri_vykl_ACC)) )  // тут REM_timer_pri_vykl_ACC (1000)- это на сколько раньше выключать выход REM перед остальными выключениями
                          
{
                          
REM 0;    //digitalWrite(REMpin, 0); // сразу выключаем усилитель звука
                          
flagREM 0/* выключаем флаг выхода REM*/ // обнуляем статус REM
                          
}
 
/*пауза 7c или 2c после вЫключения ACC и потом делать следующ://через 5с после выключения зажигания вЫключаем минус на OTG, ВЫключаем хаб, вЫключаем +5V (POGO(USB)), тушим экран (если прошло 2мин со старта БП)*/
  
  
if (((millis() - pauseTimeACC) >= (100)) )
      {
      if (
flagACC==&& flagAKB==0){STARTUEM 1;}  // определяем предположительный старт авто c задержкой XXXмс
      


if (
HALL_as_power_Switch == 0)
//if (HALL_as_power_Switch == 0)
      
if (((millis() - pauseTimeACC) >= (timeAfterACC+SLEEP_timer_pri_vykl_ACC)) ) 
                                                    {
                                                        if (
flagHALL == 1)
                                                                 {
SLEEP 1;}//digitalWrite(SLEEPpin, 1); /*тушим экран (если прошло 2 минуты с момента включения блока )*/
                                                            
else {SLEEP 0;}//{digitalWrite(SLEEPpin, 0);}
                                                    
}
//if (HALL_as_power_Switch == 0)                                                     
if (HALL_as_power_Switch == 1)
{
//if (HALL_as_power_Switch == 1)
    
if (millis() - pauseTimeACC >= SLEEP_timer_pri_vykl_ACC )    {SLEEP 1;}//digitalWrite(SLEEPpin, 0); /*включаем экран*/
    
if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vykl_ACC+500) ) { SLEEP 0;}
    
//if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vykl_ACC+1000) ) { SLEEP = 1;}
}//if (HALL_as_power_Switch == 1)
    
                                                    
    
if ( ((millis() - pauseTimeACC) >=  (OTG_timer_pri_vykl_ACC+timeAfterACC))  ) /* 3000 пауза 3с чтобы не пукал усилитель*/
                                                            
{
                                                            
OTG 0;//digitalWrite(OTGpin, 0); /*вЫключаем минус на OTG (8 pin PW1)*/
                                                           
                                                            
}
    if ( ((
millis() - pauseTimeACC) >=  (FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC+timeAfterACC))  ) 
                                                            {
                                                            
FIVE_Volt_OUT_na_POGO_or_USB 0;//digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 0); /*вЫключаем +5V зарядки. (POGO(USB))*/
                                                            
}
 
    if ( ((
millis() - pauseTimeACC) >=  (HUB_timer_pri_vykl_ACC+timeAfterACC))  ) 
                                                            {
                                                             
HUB =0;//digitalWrite(HUBpin, 1); /* ВЫключаем хаб = подаем + на управляющий транзюк хаба, тот закрывается и не пускает +5В с KIW (2вых)на хаб*/
                                                            
}
                                                                                                                        
              
  if ( ((
millis() - pauseTimeACC) >=  (lcd_noBacklight_timer_pri_vykl_ACC+timeAfterACC))  ) 
                                                            {
                                                            
lcd.noBacklight();// тушим подсветку дисплея для newE и для 0x27 // в 409 строке включение подсветки LCD дисплея 
                                                            
}
                              
                              
    if  ( ((
millis() - pauseTimeACC) >=  (I_dva_C_szina_OFF_time timeAfterACC ))  && (razreszenie_raboty_I_dva_C_sziny  == 1) )  //когда вЫключили зажигание, по истечении времени (I_dva_C_szina_OFF_time) и если разрешение на работу I2C шины всё еще вЫключено - вЫключаем шину I2C
                                                            

                                                            
lcd.clear(); //очистка дисплея 
                                                            
razreszenie_raboty_I_dva_C_sziny  0//запрещаем работу I2C шины
                                                            // ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ТУТ надо будет вЫключать питание на TDA7442 ! ! ! ! ! ! ! ! ! 
                                                                
                                                            

    if ((
razreszenie_raboty_I_dva_C_sziny == 0) || (flagHALL ==1)) //Не даём заснуть первые 15с  
    
{Sleepy::loseSomeTime(vremia_sna_ATMEGI);}//  Т У Т   С П И М   sleep for XXX seconds   - когда запретили работу I2C шины, запускаем сон каждый цикл(loop) на 0,1 сек.                                                                                           

                                                            
 
}// if (flagACC==0)
       
//END obrabotka_ACC_OFF()


void obrabotka_AKB()
{
//START  obrabotka_AKB()
  //  -------------------------========================= блок контроля АКБ ==========================-------------------------------------------------------------------------------


if (U_acc_real >= UaccONorOFF)   {UakbONorOFF Uakb_Kogda_ACC_vkluczeno;}  else {UakbONorOFF Uakb_Kogda_ACC_vYkluczeno;} /*при включении зажигания напряжение самовырубания станет 11,1 вместо 11,9*/

  
if ((Uperezariadki U_akb_real) && ((U_akb_real >= UakbONorOFF) && flagAKB == 0)) /*проверка +30 на перезаряд >15.5В, и больше заданного в 266 строке, и флага акб */
    
{
      if ((
millis() - pauseTimeACC >= 100) && flagAKB == 0)
        {
        
SAMOZAPITKA =1;//digitalWrite(SAMOZAPITKApin, 1);  /* включаем самозапитку процессора        */
        
flagAKB 1/*подняли флаг батареи*/
        
}
    }
   
//Serial.print ("razreszenie_raboty_I_dva_C_sziny = "  ); Serial.println (razreszenie_raboty_I_dva_C_sziny);
 
if (((U_akb_real UakbONorOFF) && flagAKB == 1)||(U_akb_real >Uperezariadki))/* ситуация, когда сел при работе ардуины аккумулятор, либо сел в процессе работы или простоя автомобиля, либо перезарядка > 15.5В*/
    

      
flagAKB 0;//спустили флаг батареи
      
flagACC 0;
      
pauseTimeACC millis();
      
pauseTimeAKB millis();
      
UakbONorOFF Uakb_Kogda_ACC_vYkluczeno;
    }

  if ((
millis() - pauseTimeAKB >= timeWhileAkbLow) && flagAKB == 0/* если севший аккумулятор //через 40с вЫключаем питание на батарею планшета и вырубаем сам БП.*/
    
{    
      
PlanshBAT 0;          //digitalWrite(PlanshBATpin, 0);       /*вЫключаем питание на батарею планшета */
      
OTG 0;                //digitalWrite(OTGpin, 0);             /*вЫключаем минус на OTG )*/
      
FIVE_Volt_OUT_na_POGO_or_USB 0;    //digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 0); /*вЫключаем +5V (POGO(USB))*/
      
HUB 0;                //digitalWrite(HUBpin, 1);             /* подаем + на управляющий транзюк хаба, тот закрывается и не пускает +5В с KIW (2вых)на хаб = ВЫключаем хаб*/
      
REM 0;                //digitalWrite(REMpin, 0);             /* выключаем выход REM*/
      
REGISTRATOR 0;        //digitalWrite(REGISTRATORpin, 0);     /* выключаем питание  на видеорегистратор*/
      
SAMOZAPITKA =0;         //digitalWrite(SAMOZAPITKApin, 0);     /*выключаем SAMOZAPITKApin, при этом пропадает управление на IN4, система ПОЛНОСТЬЮ обесточивается*/
      
UPRAVLENIE_PINAMI(); 
      
delay (5000);         // задержка для аппаратного выключения
    
}

  if (
flagAKB == && flagACC == 0)  /*ситуация, когда норм акб и выключено зажигание (ACC)*/
  
{
    if ((
millis() - pauseTimeAKB )>= timeUntilBATOff && flagAKB == 1)    /* если прошло "timeUntilBATOff" 24 (86400000) часа, как выключили ACC // пауза  (3600000 - 60мин) (60000 - 1 мин)(10800000=3ч) (1800000=5ч)*/
      

        
PlanshBAT 0;                                            // digitalWrite(PlanshBATpin, 0);  /*вЫключаем питание на батарею планшета (in2)//(батарея планшета))*/
      
}

    if ((
millis() - pauseTimeAKB) >= timeUntilALLOff && flagAKB == 1)   /* если давно выключили ACC     ) "timeUntilALLOff" (2суток = 172800000))     (самозапитка для регистратора, процессор БП активен)*/
      
REGISTRATOR 0//digitalWrite(REGISTRATORpin, 0);       /* выключаем питание  на видеорегистратор*/
        
SAMOZAPITKA 0;  //digitalWrite(SAMOZAPITKApin, 0);      /*выключаем SAMOZAPITKApin, при этом система ПОЛНОСТЬЮ обесточивается*/
        
UPRAVLENIE_PINAMI(); 
        
delay (10000);              // задержка для аппаратного выключения
      
}
  }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~конец блока обработки напряжений  АКБ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    
//END obrabotka_AKB()

void loop()
{while (
1){//для ускорения void loop
           
analogReadU (5);//вызов функции усреднённого чтения аналоговых входов - прочитали сырые данные с АЦП АКБ и АСС, потом их усреднили(5)раз.

if (kalibrovkaNOW != 255 && digitalRead(PINkalibrovki)== 0){if (  (millis() < 60000) || kalibrovkaNOW >= )  { rejim_kalibrovki();}      }  //    после 60с или если стоит ЗАПРЕТ(255), калибровку НЕ ДЕЛАЕМ



// новое ( с T12 версии)  вычисление реального напряжения, с учетом значений калибровки в еепром (0 и 1 адреса)
U_acc_real =  Uacc * (1410.0+kalibrovkaACC)/100000;
U_akb_real =  Uakb * (1410.0+kalibrovkaAKB)/100000;


 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ кусок кода ниже нужен для того, чтобы при включении  и сразу выключении ACC при полностью выключенном планшете(холодный старт) экран мог тухнуть по сигналу датчика холла.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  
if ( (millis() > pauseTimeHALL && flagHALL == )|| ((millis() > 15000) && flagACC == 1)) 
  {
flagHALL 1;} /*проверка отсчета при холодном старте при включении  и сразу выключении ACC*/
  /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~проверка, выключили ли мы зажигание или просто стартуем ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
if ((U_akb_real U_acc_real) >=)/*проверка, выключили ли мы зажигание или просто стартуем, нужно для того, чтобы не моргать экраном при стартере и быстро тушить экран при выключении зажигания.*/
          
{timeAfterACC timeAfterACC_accOFF; } //выключили зажигание.
     
else { timeAfterACC timeAfterACC_starting;     if (U_akb_real <=UakbONorOFF) {flagREM 3;REM 0;}   }//заводим машину (стартуем) или сел акб при включенном зажигании.
         
if (U_akb_real >= Uperezariadki){timeAfterACC 0;}


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/



  //  ------------========================== блок ACC ========================-----------------------------------------------------------------------------
obrabotka_ACC_ON(); // запустили блок обработки ACC (обработка режима включённого зажигания)
obrabotka_ACC_OFF(); // запустили блок обработки ACC (обработка режима вЫключенного зажигания)
 
  //  -------------------------========================= блок контроля АКБ ==========================------------------------------------------------------------------------------- 
obrabotka_AKB(); // запустили блок обработки АКБ

 



/******************************************индикация светодиодом и задержка вывода на дисплей********************************************************************************************************************************************************************************/
   
ms millis();
  
// Событие срабатывающее каждые 125 мс
  
if ( ( ms ms1 ) > 125 || ms ms1 ) {
    
ms1 ms;
    
// Режим светодиода ищем по битовой маске
    
if (  blink_mode << (blink_loop 0x07) ) {LED 1;}
    else { 
LED 0;}
    
blink_loop++;
  }
 
if (
razreszenie_raboty_I_dva_C_sziny  == 1// если разрешена работа для шины I2C 
{
  
// Событие срабатывающее каждые 350 мс
  
if ( ( ms pauseDisplay ) > vremia_obnovlenia_displeya || ms pauseDisplay 
  { 
   
pauseDisplay ms;
   
printDISPLAY(); // выводим на дисплей раз в 350( запуская фушкцию)
  
}
}  
  
  
 

 
/*настраиваем режимы моргания встроенного светодиода ардуины*/  
  
if (blink_mode != modes[5] || blink_mode != modes[5]) 
  {
  if (
flagAKB == ){blink_mode modes[4];}                 // индикация напруги батареи на ардуинине.- низкое напряжение АКБ авто - Две короткие вспышки раз в секунду 
  
if (flagAKB == && flagACC == 0) {blink_mode modes[3];} //- нормальное напряжение АКБ авто, ACC выключено.                     - Короткая вспышка раз в секунду
  
if (flagAKB == && flagACC == 1) {blink_mode modes[2];} //- нормальное напряжение, включено ACC, рабочий режим.                - Мигание по 0.8 сек
  
if (kalibrovkaNOW >= 1) {blink_mode modes[1];} // режим калибровки
      
  

 
/* ***********************данные для справки****************************************************************
    0B00000000, //Светодиод выключен blink_mode = modes[0]; 
    0B11111111, //Горит постоянно blink_mode = modes[1];      
    0B00111111, //Мигание по 0.8 сек  blink_mode = modes[2]; 
    0B00000001, //Короткая вспышка раз в секунду  = modes[3]; 
    0B00000101, //Две короткие вспышки раз в секунду 
    0B00010101, //Три короткие вспышки раз в секунду
    0B01010101  //Частые короткие вспышки (4 раза в секунду)= blink_mode = modes[6]; 
   */
//**********************************************************************************************************


//Serial.print ("HUB = "  ); Serial.println (HUB); 
if (STARTUEM == 1// когда крутим стартером ( заводимся) 
//если включено в настройках
    
if (power_off_HUB_on_starting == 1){HUB 0;} // выключаем питание на хаб в момент старта, если включено в настройках
    
if (power_off_OTG_on_starting ==1) {OTG 0;} // выключаем массу на OTG в момент старта, если включено в настройках
}

UPRAVLENIE_PINAMI(); 




}} 
/*конец цикла void loop() и конец while (1)*/
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//=========================================================================================================================================================================================================================================================================== 
oleg707 вне форума   Ответить с цитированием
Старый 15.05.2018, 22:45   #19
oleg707
Гуру
 
Аватар для oleg707
 
Регистрация: 16.04.2014
Возраст: 40
Город: Gdynia
Регион: другой - для добавления сообщить ab
Сообщений: 2,548
oleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond repute
Arrow добавил возможность сохранять персональные настройки в EEPROM

поскольку пользователей блока стало много, и некоторым нужно ну СОВСЕМ разное поведение, и они вынуждены каждое обновление прошивки прописывать свои настройки ( напряжения, режмы работы и т.п. ), я добавил возможность сохранять персональные настройки в энергонезависимую память процессора (EEPROM). ( пока некоторые).

Для тех, кто не изучал скетч, и НЕ понимает, для чего это нужно, обновление ничего не меняет, он "прозрачное".
То есть если вы один раз настраивали блок питания "под себя" и сохранили это в память блока, то последующие обновления прошивки будут пытаться сначала считать эти настройки, а если их нет, то берутся значения "по умолчанию".

m31_eprom.zip

Последний раз редактировалось oleg707; 22.05.2018 в 23:57.
oleg707 вне форума   Ответить с цитированием
Старый 22.05.2018, 23:58   #20
oleg707
Гуру
 
Аватар для oleg707
 
Регистрация: 16.04.2014
Возраст: 40
Город: Gdynia
Регион: другой - для добавления сообщить ab
Сообщений: 2,548
oleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond reputeoleg707 has a reputation beyond repute
Arrow

тестовая версия.
m32 - Реализована возможность ВСЕ настройки пользователя (в том числе и тайминги) писать в энергонезависимую память (EEPROM). Настройки НЕ совместимы с серсией m31, поэтому их надо переписать еще раз (brac_nastrojki_iz_EEPROM =1)
добавлена настройка vremia_uderjanija_najatoj_knopki_POWER. уменьшено время сна атмеги с 100 до 50, на потребление не повлияло.

const byte brac_nastrojki_iz_EEPROM = 0;
// если вы хотите СОХРАНИТЬ свои настройки в энергонезависимую память(еепром), тогда ставим 1,
0 - берём значения из скетча, игнорируя память ( кроме калибровки),
2 - берем значения из памяти eeprom,(если память пустая, берем значения из скетча.)

PHP код:
byte ver 32;// БЕТА( чем больше цифра, тем новее)
byte TipBlokaPitania 255// 177 - BP7. 255 - BP5mini //выбор типа блока питания.
// дата правки 22.05.18.2223

// для 5mini, 5mini2,1 версии блока питания. 
// скетч проверен и записан на версии ардуино IDE 1.9.0  1,8,1 win7, 1.63 xp
// МОЮ сборку ардуино можно скачать тут  https://drive.google.com/file/d/1oAzCQYh9XUnrhFRb314IWGtA45K7Vonh/view?usp=sharing


//Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
// Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
//  Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И  
//   Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
   
const byte brac_nastrojki_iz_EEPROM 0;      // если вы хотите СОХРАНИТЬ свои настройки в энергонезависимую память(еепром), тогда ставим 1, 0 - берём значения из скетча, игнорируя память ( кроме калибровки), 2 - берем значения из памяти eeprom,(если память пустая, берем значения из скетча.) 
 
byte reset_HUB_on_power_on 1;      // передёргивать ли хаб при каждом включении зажигания, для решения проблемы с определением изикапа (STK1160) 1 - после ВКЛ АСС включить хаб, выключить на 0,5с и включить опять. 0 - просто включить хаб.  При 1 могут быть проблемы с определением флешки в хабе, отгда поставить 0.
 
byte power_off_HUB_on_starting 1;  // выключать ли питание на хаб при старте авто ( 1- да, выключать) (0 - не выключать)
 
byte power_off_OTG_on_starting 1;  // выключать ли массу на OTG при старте авто   ( 1- да, выключать) (0 - не выключать)
 
byte HALL_as_power_Switch 0;       // 0 - используем ДХ как обычно. 1 - вместо ДХ подключаем кнопку питания планшета. Если подключено как КНОПКА, то задержка перед нажатием "кнопки" после включения АСС это SLEEP_timer_pri_vkl_ACC, а после вЫключения  SLEEP_timer_pri_vykl_ACC. Удержание нажатия = vremia_uderjanija_najatoj_knopki_POWER. ДХ = Датчик Холла.  
 
unsigned long  vremia_uderjanija_najatoj_knopki_POWER 250//если HALL_as_power_Switch = 1, то время "зажатия" (нажимания) кнопки питания планшета устанавливаем тут. 500 = 0,5с. 

//НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________
// напряжения должны быть записаны ТОЛЬКО в XX.X формате, например 11.0
  
float Uperezariadki 15.5;              // напряжение, выше которого будет считаться, что идёт перезарядка аккумулятора авто.
  
float UrabotyREM 11.8;                 // напряжение, выше которого будет работать усилитель звука, если акб не садился.
  
float UnevykluczeniaREM 13.7;          // напряжение, когда машина считается заведённой. Тогда, если завели машину, ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
  
float Uakb_Kogda_ACC_vYkluczeno 11.9;  // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вЫключенном АСС
  
float Uakb_Kogda_ACC_vkluczeno 11.1;   // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вКлюченном АСС
  
float UaccONorOFF 10.1;                // напряжение порога сработки асс.  Т.е. если на пин блока питания "вход АСС" подать ниже UaccONorOFF (11,1), то зажигание будет считаться выключенным.
//КОНЕЦ НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________НАСТРОЙКИ Пороговых напряжений!!!!!!!!_________
  
/*счётчики времени*/
  //НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!______НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!      НАСТРОЙКИ ТАЙМИНГОВ!!!
  
  
unsigned long timeUntilBATOff 345600000;                     // время до выключения питания на батарею планшета после выключения зажигания., считаем ОТ момента выключения зажигания. если прошло 48 часов, как выключили ACC // пауза  (3600000 - 60мин) (60000 - 1 мин)(10800000=3ч) (1800000=5ч)
  
unsigned long timeUntilALLOff 172800000 timeUntilBATOff;   // время до полного выключение блока,  после выключения зажигания (ACC)и уже после того, как выключится питание на батарею планшета    ) (2суток = 172800000)) (4суток = 345600000)
 
unsigned long timeBeforeRemOff 1800000;                            // 1800000=30мин. Время, оставшееся до отключения выхода REM после включения зажигания и незаводки машины. ( то есть сколько времени будет включён усилитель звука, если заглушить машину и просто слушать музыку,  при нормальном АКБ)

 
unsigned long timeAfterACC_starting 7000;                // не может быть меньше REM_timer_pri_vykl_ACC! //задержка перед началом процедуры выключения зажигания во время кручения стартером
 
unsigned long timeAfterACC_accOFF 2000;                  // не может быть меньше REM_timer_pri_vykl_ACC! //задержка перед началом процедуры выключения зажигания во время обычного выключения зажигания
 
unsigned long timeWhileAkbLow 40000;                     // 40000 время, через которое начнётся полное выключение блока когда напряжение на АКБ очень низкое.   /* если севший аккумулятор //через 40с вЫключаем питание на батарею планшета и вырубаем сам БП.*/
 
unsigned long pauseTimeHALL 140000;            // Для первого включения планшета. Раньше этого времени экран не будет тухнуть! Время паузы перед морганием-тушением экрана (для датчика холла)(равен времени загрузки планшета плюс секунд 10-20)= 2мин
 
unsigned long vremia_obnovlenia_displeya 250;  // Время, через которое будет обновляться информация на дисплей I2C  (время обновления I2C дисплея)

//тут настраиваем паузу при вКлючении зажигания ( АСС) и по истечении этого времени активируем/деактивируем  
//соответствующий пин блока питания (время независимо друг от друга)
 
unsigned long  PlanshBAT_timer_pri_vkl_ACC 1100;// пауза  после включения ACC перед включением питания на батарею планшета
 
unsigned long  FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC 1400;// пауза  после включения ACC перед включением +5V (POGO(USB) выхода для пина зарядки планшета (+5В пого или ЮСБ) 
 
unsigned long  OTG_timer_pri_vkl_ACC 50;// пауза  после включения ACC перед включением минуса на OTG ( 4й контакт ЮСБ разъема на планшете)  (включается определение ЮСБ перифирии планшетом.)
 
unsigned long  HUB_timer_pri_vkl_ACC 2100;// пауза  после включения ACC перед подачей питания на хаб. Значение должно быть больше либо равно FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC.
 
unsigned long  REGISTRATOR_timer_pri_vkl_ACC 2500;// пауза  после включения ACC перед включением  питания +12В на видеорегистратор
 
unsigned long  REM_timer_pri_vkl_ACC 2500;// пауза  после включения ACC перед включением  питания +12В на REM (включение усилителя звука)
 
unsigned long  SLEEP_timer_pri_vkl_ACC 3000// пауза  после включения ACC перед включением экрана планшета (масса на Датчик Холла)
 
unsigned long  I_dva_C_szina_ON_time 150;        //Время, через которое I2C шина включится после вКлючения зажигания - начнётся передача по шине I2C.

//тут настраиваем паузу при вЫключении зажигания ( АСС) и по истечении этого времени активируем/деактивируем 
//соответствующий пин блока питания (время независимо друг от друга)
 
unsigned long  OTG_timer_pri_vykl_ACC 2500// пауза  после вЫключения ACC перед вЫключением минуса на OTG ( 4й контакт ЮСБ разъема на планшете) (вЫключается определение ЮСБ перифирии планшетом.)
 
unsigned long  FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC 5000// пауза  после вЫключения ACC перед вЫключением +5V (POGO(USB) выхода для пина зарядки планшета (+5В пого или ЮСБ) 
 
unsigned long  HUB_timer_pri_vykl_ACC 5000// пауза после вЫключения ACC перед убиранием питания с хаба. Значение должно быть меньше либо равно FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC.
 
unsigned long  SLEEP_timer_pri_vykl_ACC 0// пауза  после вЫключения ACC перед вЫключением экрана планшета (масса на Датчик Холла)
 
unsigned long  REM_timer_pri_vykl_ACC 1000;// не может быть больше timeAfterACC_accOFF и timeAfterACC_starting!  Пауза  после вЫключения ACC перед вЫключением  питания +12В на REM (вЫключение усилителя звука), тут 1000 это на сколько раньше выключать выход REM перед остальными выключениями
 
unsigned long  lcd_noBacklight_timer_pri_vykl_ACC 17000// 7000 пауза после вЫключения ACC перед убиранием подсветки I2C LSD дисплея (1602)
 
unsigned long  I_dva_C_szina_OFF_time lcd_noBacklight_timer_pri_vykl_ACC 3000;      //Время, которое I2C шина работает после вЫключения зажигания, потом  - закончится передача по шине I2C.
 
unsigned long  rezerv2 =0;
unsigned long  rezerv3 =0;
unsigned long  rezerv4 =0;
float          rezerv5 =0;
float          rezerv6 =0;
float          rezerv7 =00.00;
 
//конец настроек таймингов.__________________________________________________________________________________________


//К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
// К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
//  К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И  
//   К О Н Е Ц      Н А С Т Р О Й К И      П О Л Ь З О В А Т Е Л Я      П О Д      С В О И      П О Т Р Е Б Н О С Т И 
   
int nachalnyj_address_dannyh_polzovatelja_v_eeprom 2;                    // Переменная для хранения начального адреса еепром

struct myStruct_Znachenija_peremennyh_i_timingov {                   // Создаем пользовательскую структуру
 
byte reset_HUB_on_power_on;      // передёргивать ли хаб при каждом включении зажигания, для решения проблемы с определением изикапа (STK1160) 1 - после ВКЛ АСС включить хаб, выключить на 0,5с и включить опять. 0 - просто включить хаб.
 
byte power_off_HUB_on_starting ;  // выключать ли питание на хаб при старте авто ( 1- да, выключать)
 
byte power_off_OTG_on_starting;   // выключать ли массу на OTG при старте авто   ( 1- да, выключать)
 
byte HALL_as_power_Switch ;       // 0 - используем ДХ как обычно. 1 - вместо ДХ подключаем кнопку питания планшета. Если подключено как КНОПКА, то задержка перед нажатием "кнопки" после включения АСС это SLEEP_timer_pri_vkl_ACC, а после вЫключения  SLEEP_timer_pri_vykl_ACC. Удержание нажатия = 0,5с. 
  
float Uperezariadki ;              // напряжение, выше которого будет считаться, что идёт перезарядка аккумулятора авто.
  
float UrabotyREM ;                 // напряжение, выше которого будет работать усилитель звука, если акб не садился.
  
float UnevykluczeniaREM ;          // напряжение, когда машина считается заведённой. Тогда, если завели машину, ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
  
float Uakb_Kogda_ACC_vYkluczeno ;  // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вЫключенном АСС
  
float Uakb_Kogda_ACC_vkluczeno ;   // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вКлюченном АСС
  
float UaccONorOFF ;                // напряжение порога сработки асс.  Т.е. если на пин блока питания "вход АСС" подать ниже UaccONorOFF (11,1), то зажигание будет считаться выключенным.
  
unsigned long timeUntilBATOff;                                // 4 байта
  
unsigned long timeUntilALLOff;                                // 4 байта
  
unsigned long timeBeforeRemOff;                               // 4 байта
 
unsigned long timeAfterACC_starting;                                // 4 байта
 
unsigned long timeAfterACC_accOFF ;                                // 4 байта
 
unsigned long timeWhileAkbLow ;                                     // 4 байта
 
unsigned long pauseTimeHALL ;                                       // 4 байта
 
unsigned long vremia_obnovlenia_displeya ;                          // 4 байта
 
unsigned long  PlanshBAT_timer_pri_vkl_ACC;                               // 4 байта
 
unsigned long  FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC;    // 4 байта
 
unsigned long  OTG_timer_pri_vkl_ACC;                                         // 4 байта
 
unsigned long  HUB_timer_pri_vkl_ACC;                                        // 4 байта
 
unsigned long  REGISTRATOR_timer_pri_vkl_ACC;                            // 4 байта
 
unsigned long  REM_timer_pri_vkl_ACC;                                        // 4 байта
 
unsigned long  SLEEP_timer_pri_vkl_ACC;                                    // 4 байта
 
unsigned long  I_dva_C_szina_ON_time;                                        // 4 байта
unsigned long  OTG_timer_pri_vykl_ACC ;                                        // 4 байта
unsigned long  FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC ;// 4 байта
unsigned long  HUB_timer_pri_vykl_ACC;                                        // 4 байта
unsigned long  SLEEP_timer_pri_vykl_ACC;                        // 4 байта
unsigned long  REM_timer_pri_vykl_ACC ;                         // 4 байта
unsigned long  lcd_noBacklight_timer_pri_vykl_ACC ;             // 4 байта
unsigned long  I_dva_C_szina_OFF_time ;                         // 4 байта
unsigned long  vremia_uderjanija_najatoj_knopki_POWER 
unsigned long  rezerv2 ;
unsigned long  rezerv3 ;
unsigned long  rezerv4 ;
float          rezerv5 ;
float          rezerv6 ;
float          rezerv7 ;
};

//***************************************************************************************************************************************************
// Массив режимов работы светодиода
byte modes[] = {
  
0B00000000//Светодиод выключен
  
0B11111111//Горит постоянно
  
0B00111111//Мигание по 0.8 сек
  
0B00000001//Короткая вспышка раз в секунду 
  
0B00000101//Две короткие вспышки раз в секунду  
  
0B00010101//Три короткие вспышки раз в секунду
  
0B01010101  //Частые короткие вспышки (4 раза в секунду) 
};
uint32_t msms1 0
uint8_t  blink_loop 0;
uint8_t  blink_mode 0;
//***************************************************************************************************************************************************
#include <JeeLib.h> // Low power functions library //для сна
ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup the watchdog //для сна
#include <Wire.h> // для дисплея - I2C шина
#include <LiquidCrystal_I2C.h> // библиотека для дисплея 
#include <EEPROM.h> // для использования ЕЕПРОМ
//#include <avr/wdt.h> //Чтобы использовать функции Watchdog нужно подключить к проекту стандартную библиотеку ( https://geektimes.ru/post/255800/ )
char     strokaI[32] = "                ";// Массив для вывода 1 строки на дисплей , объявляем длиннее(32символа), чтобы не было глюков с отображением на экране
char    strokaII[32] = "                ";// Массив для вывода 2 строки на дисплей
// ЭТО нужно для вывода на 128*64 Adafruit_SSD1306 дисплей
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display2(OLED_RESET);
#define XPOS 0
#define YPOS 1
#define DELTAY 2
// конец настройки для вывода на 128*64 Adafruit_SSD1306 дисплей
//Перед прошивкой скетча убедитесь в наличии нужных библиотек,например  d:\777\Soft\arduino\arduino-1.6.11\libraries\LiquidCrystal_I2C\   https://github.com/marcoschwartz/LiquidCrystal_I2C например
LiquidCrystal_I2C lcd(PCF8574_ADDR_A21_A11_A014561611121314POSITIVE);  // для newE  описание библиотеки http://elchupanibrei.livejournal.com/27443.html#t23347
// обьявляем переменные и задаём их начальные значениия
float UakbONorOFF 12.1//  напряжение порога сработки акб
float U_acc_real 7.0;     //  реальное напряжение +ACC на входе делителя 
float U_akb_real 7.0;     //  реальное напряжение +30 на входе делителя 
int Uacc 0;             // напряжение с делителя ACC 0-1024 
int Uakb 0;             // напряжение с делителя АКБ 0-1024    

//PORTB
const byte SAMOZAPITKA_Pin                    9;   // номер пина самозапитки блока
const byte LED_Pin                            13;  // номер пина встроенного светодиода индикации 
const byte OTG_Pin                            10;  // номер пина управляющего микросхемой, управляющей режимом OTG
const byte HUB_Pin                            11;  // номер пина управляющего транзистором, управляющего Питанием ХАБа
const byte SLEEP_Pin                          12;  // номер пина управляющего микросхемой, которая даёт массу на пин сна ( датчик холла)
 
//PORTD
const byte PlanshBAT_Pin                      6;  // номер пина управляющего микросхемой, управляющей питанием БАТАРЕЕЙ планшета (через управляющую ногу IN2-5pin )0 = нет питания; 1 = есть питание ( БАТАРЕИ планшета)
const byte REGISTRATOR_Pin                    4;  // номер пина управляющего микросхемой управляющей питанием видеорегистратора
const byte FIVE_Volt_OUT_na_POGO_or_USB_Pin   2;  // номер пина управляющего сном 2 преобразователя DC-DC (+5В)
const byte REM_Pin                            7;  // номер пина управляющего транзистором, управляющего Питанием ХАБа
 
//логические состояния блока питания (какая ножка какой сигнал должна выдавать)
    
uint8_t  PORTBregistr 0;               // Если у нас есть 8-битная переменная PORTBregistr, то мы можем присвоить её значение регистру PORTx, и тем самым установить ножки микроконтроллера в состояние, соответствующее значению переменной PORTBregistr
boolean SAMOZAPITKA 0;                     // byte SAMOZAPITKApin = 9; /*управление самозапиткой блока питания IN4*///1 = есть самозапитка; 0 = нет самозапитки
boolean LED 0;                             // Светодиод 1 = светит; 0 = не светит
boolean SLEEP=0;                             //byte SLEEPpin = ; //1 = потух экран(есть масса на пине сна); 0 = штатная работа планшета (нет массы на пине сна) ( также 0 означает ненажатую кнопку питания, если мы используем канал ДХ для управления кнопкой питания планшета.)
boolean HUB 0;                             //byte HUBpin = 11;  0-хаб вЫключен, 1 - хаб включен
boolean OTG 0;                             //byte OTGpin = ; //1 = есть масса на OTG; 0 = нет массы на OTG

    
uint8_t  PORTDregistr 0;               //  8-битная переменная PORTDregistr
boolean PlanshBAT 0;                       //byte PlanshBATpin = 6; /* 10pin = PD6 = pin D6 PWM            ..... управление питания БАТАРЕИ планшета через управляющую ногу IN2-5pin*/ //0 = нет питания; 1 = есть питание ( БАТАРЕИ планшета)
boolean REGISTRATOR 0;                     //byte REGISTRATORpin = 4; /* 2 pin = PD4 = pin D4 выход 12В для работы видеорегистратора (D4 -IN1)*/ 
boolean FIVE_Volt_OUT_na_POGO_or_USB 0;    //byte FIVE_Volt_OUT_na_POGO_or_USBpin = 2;   32pin = PD2 = pin D2         включить управление SS2 выходом питания  +5V  на пого пин(или USB), чтоб планшет думал, что идет зарядка //0 = нет 5V на POGO; 1 = есть 5V на POGO
boolean REM 0;                             //byte REMpin = 7;           11pin = PD7 = pin D7 выход сигнала REM (+12v) (IN3) //0 = нет 12В на выходе REM; 1 = есть 12В на выходе REM
 
int PINrawACC A0;   // замер для 5й версии
int PINrawAKB A1;   // замер для 5й версии
int PINkalibrovki A2// замер для 5й версии

//int PINrawACC = A7;   // замер для 7й версии
//int PINrawAKB = A8;   // замер для 7й версии
//int PINkalibrovki = A3; // замер для 7й версии
 
//пины состояния ITS
byte STATEpinI 1;        /*логический вход для отслеживания аварийной ситуации ITS716G(724G)(питание KIW3312s-out2 и регистратор-out1) 0 = авария*/
byte STATEpinII 1;       /*логический вход для отслеживания аварийной ситуации ITS716G(724G)(выход REM-out3 и самозапитка БП-out4 )1 = авар. сит.*/

/*логические переменные, используемые в коде*/

byte flagACC 0;          /*признак включенного зажигания*/
byte flagAKB 0;             /* признак заряженной батареи*/
byte flagREM 0;             /* признак включенного выхода на усилитель звука (REM) 0 1 2*/
byte kalibrovkaNOW 0// признак того, что сейчас происходит калибровка встроенного вольтметра по АСС и АКБ.
byte kalibrovkaACC =  EEPROM.read(0);  // значение для калибровки для делителя АСС
byte kalibrovkaAKB =  EEPROM.read(1); // значение для калибровки для делителя АКБ
byte razreszenie_raboty_I_dva_C_sziny  0// Разрешили ли мы работать (инициализировали ли) I2C устройствам (дисплеи, звуковой  процессор) в текущем цикле. 1 - инициализировали и разрешили, 0 - НЕ инициализировали и запретили       
byte flagHALL 0;         //флаг отработки морга экрана при холодном старте( flagHALL = 1 экран можно включать и выключать, датчик холла на планшете инициализировался)
byte STARTUEM 0;         //Стартует ли авто ( крутим ли стартером) 0- не крутим, 1 - крутим.

   





int vremia_sna_ATMEGI 50//   sleep for XXX seconds   - когда запретили работу I2C шины, запускаем сон каждый цикл(loop) на 0,1 сек. (0-200) Нужно для режима энергосбережения атмеги.                                                                                         
unsigned long eventTime 0;
unsigned long pauseTimeACC millis();      // сброс времени для отсчета отключения самозапитки
unsigned long pauseTimeAKB millis();
unsigned long pauseDisplay 0;             /* таймер для обновления информации на дисплее, чтобы не мерцал*/
unsigned long timeAfterACC 5000;          /*базовое (для инициализации) , ни на что не влияет.  Меняйте   timeAfterACC_accOFF и timeAfterACC_starting   !        время после выключения зажигания, после истечения которого вырубается экран, хаб, otg-режим*/
unsigned long TimerREM 0;                 /*базовое (для инициализации) , ни на что не влияет.  Отсчет до выключения выхода REM при заглушенном авто и включенном зажигании.3600000 = час */
unsigned long TIMER millis();             /*базовое (для инициализации) , ни на что не влияет. */
unsigned long H = (millis()/3600000); // часы 
byte M = ((millis()-(H*3600000))/60000); //минуты
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================




void UPRAVLENIE_PINAMI() // функция перевода логических параметров в реальные состояния пинов   // http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry  // https://geektimes.ru/post/255744/ Ускоряем свою Arduino   /* http://robotosha.ru/arduino/digitalwrite-optimizing-arduino.html */
{// UPRAVLENIE_PINAMI ~~~//тут мы сначала пишем  в переменную регистры, а потом сделаем PORTB = PORTBregistr; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
// PORTBregistr - обрабатывем регистры порта B атмеги

/*        if (LED == 1 ){ PORTBregistr |= 1<<5;     } //PORTB |= 1<<5; //установит "1" (сигнал высокого уровня) на выводе PB5. //digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
             else { PORTBregistr &= ~(1<<5);  } //PORTB &= ~(1<<5); //установит "0" (сигнал низкого уровня) на выводе PB5. //digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
     if (SAMOZAPITKA == 1){ PORTBregistr |= (1 << 1); } else {PORTBregistr &= ~((1 << 1));}         //PB1 управление самозапиткой блока питания IN4///1 = есть самозапитка; 0 = нет самозапитки //http://microsin.net/programming/avr/accessing-avr-ports-with-winavr-gcc.html
             if (OTG == 1){ PORTBregistr |= (1 << 2); } else {PORTBregistr &= ~((1 << 2));}         //byte SLEEPpin = 10;  PB2  управление транзюком сна VT4 (на датчик холла)) //1 = потух экран(есть масса на пине сна); 0 = штатная работа планшета (нет массы на пине сна)
           if (HUB == 0)  { PORTBregistr |= (1 << 3); } else {PORTBregistr &= ~((1 << 3));}         //HUB =0;//byte HUBpin = 11;  PB3 управление транзюком питания хаба // 1-есть питание, 0 - нет питания
         if (SLEEP == 0)  { PORTBregistr |= (1 << 4); } else {PORTBregistr &= ~((1 << 4));}         //bool OTG = 0; //byte OTGpin = 12; /* 16pin = PB4 = pin D12 MISO управление транзюком OTG Q1 //1 = есть масса на OTG; 0 = нет массы на OTG
*/
      
digitalWrite(LED_PinLED);                   //управление встроенным светодиодом
      
digitalWrite(SAMOZAPITKA_PinSAMOZAPITKA);   // управление самозапиткой блока питания 1 = есть самозапитка; 0 = нет самозапитки //http://microsin.net/programming/avr/accessing-avr-ports-with-winavr-gcc.html
      
digitalWrite(OTG_PinOTG);                   // управление OTG    
      
digitalWrite(HUB_Pin, !HUB);                  // управление транзистором питания хаба // 1-есть питание, 0 - нет питания
      
digitalWrite(SLEEP_Pin, !SLEEP);               // управление микросхемой, которая даёт массу на пин сна ( датчик холла)
    
     
// PORTDregistr - обрабатывем регистры порта D атмеги
//PORTD

 
digitalWrite(PlanshBAT_PinPlanshBAT);        //управление питанием БАТАРЕЕЙ планшета (+4,0)
 
digitalWrite(REGISTRATOR_PinREGISTRATOR);    //управление питанием видеорегистратора (+12)
 
digitalWrite(FIVE_Volt_OUT_na_POGO_or_USB_PinFIVE_Volt_OUT_na_POGO_or_USB);   //управление вторым преобразователем DC-DC (+5В)
 
digitalWrite(REM_PinREM);                    //управление выходом REM (+12)
 
 
//       if (PlanshBAT == 1){ PORTDregistr |= (1 << 6); } else {PORTDregistr &= ~((1 << 6));}         //bool PlanshBAT = 0; //byte PlanshBATpin = 6;  10pin = PD6 = pin D6 PWM    включить 1 канал KIW            ..... управление питания БАТАРЕИ планшета через управляющую ногу IN2-5pin //0 = нет питания; 1 = есть питание ( БАТАРЕИ планшета)
     
if (REGISTRATOR == 1){ PORTDregistr |= (<< 4); } else {PORTDregistr &= ~((<< 4));}         //bool REGISTRATOR = 0;   //byte REGISTRATORpin = 4;  2 pin = PD4 = pin D4 выход 12В для работы видеорегистратора (D4 -IN1)
 
if (FIVE_Volt_OUT_na_POGO_or_USB == 1){ PORTDregistr |= (<< 2); } else {PORTDregistr &= ~((<< 2));}         //bool FIVE_Volt_OUT_na_POGO_or_USB = 0;   //byte FIVE_Volt_OUT_na_POGO_or_USBpin = 2;   32pin = PD2 = pin D2         включить 2 канал KIW    управление SS2 выходом питания  +5V (2 канал kiw3312s) на пого пин(или USB), чтоб планшет думал, что идет зарядка //0 = нет 5V на POGO; 1 = есть 5V на POGO
             
if (REM == 1){ PORTDregistr |= (<< 7); } else {PORTDregistr &= ~((<< 7));}         //bool REM = 0; //byte REMpin = 7;           11pin = PD7 = pin D7 выход сигнала REM (+12v) (IN3) //0 = нет 12В на выходе REM; 1 = есть 12В на выходе REM

           // Serial.print ("PORTB, BIN = "  ); Serial.println (PORTB, BIN); // вывели порт B атмеги на монитор порта
           // Serial.print ("PORTDregistr, BIN = "  ); Serial.println (PORTDregistr, BIN); // вывели порт D атмеги на монитор порта
           // Serial.print ("SAMOZAPITKA = "  ); Serial.println (SAMOZAPITKA);
//PORTD = PORTDregistr; //прописали порту D атмеги в регистры команду на запись нулей и единиц.
//PORTB = PORTBregistr; //прописали порту B атмеги в регистры команду на запись нулей и единиц.
}//конец UPRAVLENIE_PINAMI ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 



void setup() //настройки
{

 
  
RABOTA_z_EEPROM(); //

  
Serial.begin(115200);

if( 
kalibrovkaACC == 255 ){kalibrovkaACC=127;} // проверяем , прописана ни калибровка в еепром, если нет( 255), то берём значения по умолчанию  
if( kalibrovkaAKB == 255 ){kalibrovkaAKB=127;} // проверяем , прописана ни калибровка в еепром, если нет( 255), то берём значения по умолчанию  =127

// настройки портов  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~   
 
DDRD 0b11010100;  //работает!!
 
DDRB 0b00111110;  //работает!!
 
pinMode(PINkalibrovkiINPUT);  // пин калибровки
 
digitalWrite(PINkalibrovki1); // подтяжка +5 пина калибровки
// конец настроек портов  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 

//настройки состояний при подаче питания на БП ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 
  
PlanshBAT 0;          //digitalWrite(PlanshBATpin, 0);  //вЫключаем питание на батарею планшета
  
SAMOZAPITKA 0;        // digitalWrite(SAMOZAPITKApin, 0);  //выключаем SAMOZAPITKApin, при этом пропадает управление на IN4, система ПОЛНОСТЬЮ обесточивается
  
OTG 0;                //digitalWrite(OTGpin, 0); //вЫключаем минус на OTG (8 pin PW1)
  
FIVE_Volt_OUT_na_POGO_or_USB 0;    //digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 0); //вЫключаем +5V (POGO(USB))
  
HUB 0;                //digitalWrite(HUBpin, 1); // подаем + на управляющий транзюк хаба, тот закрывается и не пускает +5В с KIW (2вых)на хаб = ВЫключаем хаб
  
REM 0;                //digitalWrite(REMpin, 0); // // выключаем выход REM
  
REGISTRATOR 0;        //digitalWrite(REGISTRATORpin, 0); // выключаем питание  на видеорегистратор
//  wdt_enable (WDTO_2S);   // Запуск таймера watchdog:   Для тестов не рекомендуется устанавливать значение менее 8 сек. Таймер будет считать ровно столько, сколько указано в константе. По истечении этого времени произойдет перезагрузка. /* Возможные значения для константы WDTO_15MS WDTO_30MS WDTO_60MS WDTO_120MS WDTO_250MS WDTO_500MS WDTO_1S WDTO_2S WDTO_4S WDTO_8S 2 s   (WDTO_2S  ATMega 8, 168, 328, 1280, 2560) (   wdt_enable (WDTO_8S);) https://geektimes.ru/post/255800/ https://tushev.org/articles/arduino/5/arduino-and-watchdog-timer     
 //UPRAVLENIE_PINAMI();     //сделать пллавный пуск - определить нужное состояние пинов без их предварительного дергания --- настроили логику и отдали её в функцию UPRAVLENIE_PINAMI. 
 //конец настроек состояний при подаче питания на БП~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 
}
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================

void displayDataToDISPLAY()//>>>>>>>>>>>>>> Сформировали строки, теперь надо их вывести на дисплеи:>>>>>>>>>>>>>> 
{//void displayDataToDISPLAY()
//вывод на 2хстрочный дисплей LCM 1602 с I2C ( на базе расширителя портов PCF8574)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    //Serial.print("strokaI  = "); Serial.println(strokaI);  // раскомментить для вывода информации в ком порт для отладки
    
lcd.setCursor(00);
    
lcd.print(strokaI);
  
    
//Serial.print("strokaII = "); Serial.println(strokaII); // раскомментить для вывода информации в ком порт для отладки
    
lcd.setCursor(01); //2строка 0символ 
    
lcd.print(strokaII);


    
//вывод на 128*64 дисплей (Adafruit_SSD1306) первой строки
                                                        
                                                          
display2.clearDisplay();        // очистили буфер 
                                                          
display2.setTextSize(1);        // установили размер текста (1-4)
                                                          
display2.setCursor(0,0);        // начальная точка вывода
                                                          
display2.println(strokaI);      // скинули значение I строки в буфер 128*64 дисплея
    //вывод на 128*64 дисплей (Adafruit_SSD1306) второй строки
                                                          
display2.println(strokaII);     // скинули значение II строки в буфер 128*64 дисплея
            
if ( ((millis() - pauseTimeACC) >=  (5000+timeAfterACC)) && (flagACC==0) )    // после 5 сек после выключения зажигания буфер будет чиститься перед выводом, соответственно на 128*64 Adafruit_SSD1306 дисплей выводиться ничего не будет Это нужно для того, чтобы ночью экран не светился ( так как пиксели активные и дают свет без подсветки) 
                                                          
{
                                                          
display2.clearDisplay();        // очистили буфер           
                                                          

                                                          
display2.display();             //эта строка выводит картинку 1306 из буфера на экран!
//Вывод строк окончен.______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
      
}//void displayDataToDISPLAY()
void IntToCharI(int numchar *text)//функция, возвращающая число в текстовый вид 0 1
{
  
//text[0] = (num/100) + '0'; // первое значение _00 - эта строчка нужна для 3хзначного числа.
  //text[1] = ((num/10)%10) + '0';// второе значение __0
  
text[2] = (num%10) + '0'// третее значение ___
 
}

void IntToCharII(int numchar *text)//функция, возвращающая число в текстовый вид 00 11
{
  
//text[0] = (num/100) + '0'; // первое значение _00 - эта строчка нужна для 3хзначного числа.
  
text[0] = ((num/10)%10) + '0';// второе значение __0
  
text[1] = (num%10) + '0'// третее значение ___
 
}


void IntToCharIII(int numchar *text)//функция, возвращающая число в текстовый вид 00 11
{
  
text[0] = (num/100) + '0'// первое значение _00 - эта строчка нужна для 3хзначного числа.
  
text[1] = ((num/10)%10) + '0';// второе значение __0
  
text[2] = (num%10) + '0'// третее значение ___
}
  
void IntToCharIIII(int numchar *text)//функция, возвращающая число в текстовый вид 0000 1111
{
 
text[0] = (num/1000) + '0';//0 знач
 
text[1] = (num/100)%10 '0'// первое значение _00 - эта строчка нужна для 3хзначного числа.
 
text[2] = ((num/10)%10) + '0';// второе значение __0
 
text[3] = (num%10) + '0'// третее значение ___
}
void FloatToCharIIIII(float numchar *text)//функция, возвращающая число в текстовый вид 00.00 11.11
{

  
int Int num*100;
 
text[0] = (Int/1000) + '0';//0 знач   7896
 
text[1] = (Int/100)%10 '0'// первое значение _00 - эта строчка нужна для 3хзначного числа.
 
text[2] =  '.';
 
text[3] = ((Int/10)%10) + '0';// второе значение __0
 
text[4] = (Int%10) + '0'// третее значение ___
}

void RABOTA_z_EEPROM ()

{
//void RABOTA_z_EEPROM ()





if (brac_nastrojki_iz_EEPROM == 1)//1 - ПИШЕМ в еепром значения из скетча.  
    
{//if (brac_nastrojki_iz_EEPROM == 1)
myStruct_Znachenija_peremennyh_i_timingov znachenija_polzovatelia[] = // Создаем массив объектов пользовательской структуры из значений, прописанных в скетче в настройках пользователя
{//myStruct_Znachenija_peremennyh_i_timingov znachenija_polzovatelia           
 
{// Создаем массив объектов
  
reset_HUB_on_power_on ,      // передёргивать ли хаб при каждом включении зажигания, для решения проблемы с определением изикапа (STK1160) 1 - после ВКЛ АСС включить хаб, выключить на 0,5с и включить опять. 0 - просто включить хаб.
  
power_off_HUB_on_starting ,  // выключать ли питание на хаб при старте авто ( 1- да, выключать)
  
power_off_OTG_on_starting ,  // выключать ли массу на OTG при старте авто   ( 1- да, выключать)
  
HALL_as_power_Switch ,       // 0 - используем ДХ как обычно. 1 - вместо ДХ подключаем кнопку питания планшета. Если подключено как КНОПКА, то задержка перед нажатием "кнопки" после включения АСС это SLEEP_timer_pri_vkl_ACC, а после вЫключения  SLEEP_timer_pri_vykl_ACC. Удержание нажатия = 0,5с. 
   
Uperezariadki,              // напряжение, выше которого будет считаться, что идёт перезарядка аккумулятора авто.
   
UrabotyREM,                 // напряжение, выше которого будет работать усилитель звука, если акб не садился.
   
UnevykluczeniaREM,          // напряжение, когда машина считается заведённой. Тогда, если завели машину, ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
   
Uakb_Kogda_ACC_vYkluczeno,  // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вЫключенном АСС
   
Uakb_Kogda_ACC_vkluczeno ,  // напряжение, ниже которого АКБ авто будет считаться разряженным (севшим) при вКлюченном АСС
   
UaccONorOFF,                // напряжение порога сработки асс.  Т.е. если на пин блока питания "вход АСС" подать ниже UaccONorOFF (11,1), то зажигание будет считаться выключенным.
   
timeUntilBATOff,                     // время до выключения питания на батарею планшета после выключения зажигания., считаем ОТ момента выключения зажигания. если прошло 48 часов, как выключили ACC // пауза  (3600000 - 60мин) (60000 - 1 мин)(10800000=3ч) (1800000=5ч)
   
timeUntilALLOff ,                    // время до полного выключение блока,  после выключения зажигания (ACC)и уже после того, как выключится питание на батарею планшета    ) (2суток = 172800000)) (4суток = 345600000)
  
timeBeforeRemOff ,                    // 1800000=30мин. Время, оставшееся до отключения выхода REM после включения зажигания и незаводки машины. ( то есть сколько времени будет включён усилитель звука, если заглушить машину и просто слушать музыку,  при нормальном АКБ)
  
timeAfterACC_starting ,               // не может быть меньше REM_timer_pri_vykl_ACC! //задержка перед началом процедуры выключения зажигания во время кручения стартером
  
timeAfterACC_accOFF ,                 // не может быть меньше REM_timer_pri_vykl_ACC! //задержка перед началом процедуры выключения зажигания во время обычного выключения зажигания
  
timeWhileAkbLow,                      // 40000 время, через которое начнётся полное выключение блока когда напряжение на АКБ очень низкое.   /* если севший аккумулятор //через 40с вЫключаем питание на батарею планшета и вырубаем сам БП.*/
  
pauseTimeHALL ,                       // Для первого включения планшета. Раньше этого времени экран не будет тухнуть! Время паузы перед морганием-тушением экрана (для датчика холла)(равен времени загрузки планшета плюс секунд 10-20)= 2мин
  
vremia_obnovlenia_displeya,           // Время, через которое будет обновляться информация на дисплей I2C  (время обновления I2C дисплея)
   
PlanshBAT_timer_pri_vkl_ACC  ,       // пауза  после включения ACC перед включением питания на батарею планшета
   
FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC// пауза  после включения ACC перед включением +5V (POGO(USB) выхода для пина зарядки планшета (+5В пого или ЮСБ) 
   
OTG_timer_pri_vkl_ACC ,              // пауза  после включения ACC перед включением минуса на OTG ( 4й контакт ЮСБ разъема на планшете)  (включается определение ЮСБ перифирии планшетом.)
   
HUB_timer_pri_vkl_ACC ,              // пауза  после включения ACC перед подачей питания на хаб. Значение должно быть больше либо равно FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC.
   
REGISTRATOR_timer_pri_vkl_ACC,       // пауза  после включения ACC перед включением  питания +12В на видеорегистратор
   
REM_timer_pri_vkl_ACC ,              // пауза  после включения ACC перед включением  питания +12В на REM (включение усилителя звука)
   
SLEEP_timer_pri_vkl_ACC,             // пауза  после включения ACC перед включением экрана планшета (масса на Датчик Холла)
   
I_dva_C_szina_ON_time ,              //Время, через которое I2C шина включится после вКлючения зажигания - начнётся передача по шине I2C.
   
OTG_timer_pri_vykl_ACC ,             // пауза  после вЫключения ACC перед вЫключением минуса на OTG ( 4й контакт ЮСБ разъема на планшете) (вЫключается определение ЮСБ перифирии планшетом.)
   
FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC // пауза  после вЫключения ACC перед вЫключением +5V (POGO(USB) выхода для пина зарядки планшета (+5В пого или ЮСБ) 
   
HUB_timer_pri_vykl_ACC ,             // пауза после вЫключения ACC перед убиранием питания с хаба. Значение должно быть меньше либо равно FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC.
   
SLEEP_timer_pri_vykl_ACC ,           // пауза  после вЫключения ACC перед вЫключением экрана планшета (масса на Датчик Холла)
   
REM_timer_pri_vykl_ACC ,             // не может быть больше timeAfterACC_accOFF и timeAfterACC_starting!  Пауза  после вЫключения ACC перед вЫключением  питания +12В на REM (вЫключение усилителя звука), тут 1000 это на сколько раньше выключать выход REM перед остальными выключениями
   
lcd_noBacklight_timer_pri_vykl_ACC,  // 7000 пауза после вЫключения ACC перед убиранием подсветки I2C LSD дисплея (1602)
   
I_dva_C_szina_OFF_time,              //Время, которое I2C шина работает после вЫключения зажигания, потом  - закончится передача по шине I2C.
   
vremia_uderjanija_najatoj_knopki_POWER,
   
rezerv2,
   
rezerv3,
   
rezerv4,
   
rezerv5,
   
rezerv6,
   
rezerv7
 
}// конец Создаем массив объектов
};//myStruct_Znachenija_peremennyh_i_timingov znachenija_polzovatelia
EEPROM.put(nachalnyj_address_dannyh_polzovatelja_v_eepromznachenija_polzovatelia);    // ПИШЕМ пакет данных в EEPROM из созданнго массива (znachenija_polzovatelia) начиная с адреса (nachalnyj_address_dannyh_polzovatelja_v_eeprom)
    
}//if (brac_nastrojki_iz_EEPROM == 1)
        
if (brac_nastrojki_iz_EEPROM == 2//2 - берем значения из памяти eeprom, игнорируя скетч (если память пустая, берем(оставляем) значения из скетча.) 
    
{//if (brac_nastrojki_iz_EEPROM == 2)
     
myStruct_Znachenija_peremennyh_i_timingov znachenija_polzovatelia// В переменную znachenija_polzovatelia будем считывать данные из EEPROM
 
EEPROM.get (nachalnyj_address_dannyh_polzovatelja_v_eepromznachenija_polzovatelia); 
 
// теперь считанные данные из переменной znachenija_polzovatelia вытаскиваем и присваеваем соответственной переменоой
//но только ЕСЛИ reset_HUB_on_power_on равно 0 или 1 ( косвенный признак нормально записанных данных в ЕЕПРОМ)
if (znachenija_polzovatelia.reset_HUB_on_power_on<2)
{    
//if znachenija_polzovatelia.reset_HUB_on_power_on)
reset_HUB_on_power_on znachenija_polzovatelia.reset_HUB_on_power_on;
power_off_HUB_on_starting znachenija_polzovatelia.power_off_HUB_on_starting;
power_off_OTG_on_starting znachenija_polzovatelia.power_off_OTG_on_starting;
HALL_as_power_Switch znachenija_polzovatelia.HALL_as_power_Switch;
Uperezariadki znachenija_polzovatelia.Uperezariadki;
UrabotyREM znachenija_polzovatelia.UrabotyREM;
UnevykluczeniaREM znachenija_polzovatelia.UnevykluczeniaREM;
Uakb_Kogda_ACC_vYkluczeno znachenija_polzovatelia.Uakb_Kogda_ACC_vYkluczeno;
Uakb_Kogda_ACC_vkluczeno znachenija_polzovatelia.Uakb_Kogda_ACC_vkluczeno;
UaccONorOFF znachenija_polzovatelia.UaccONorOFF;
timeUntilBATOff znachenija_polzovatelia.timeUntilBATOff;
timeUntilALLOff znachenija_polzovatelia.timeUntilALLOff;
timeBeforeRemOff znachenija_polzovatelia.timeBeforeRemOff;
timeAfterACC_starting znachenija_polzovatelia.timeAfterACC_starting;
timeAfterACC_accOFF znachenija_polzovatelia.timeAfterACC_accOFF;
timeWhileAkbLow znachenija_polzovatelia.timeWhileAkbLow;
pauseTimeHALL znachenija_polzovatelia.pauseTimeHALL;
vremia_obnovlenia_displeya znachenija_polzovatelia.vremia_obnovlenia_displeya;
PlanshBAT_timer_pri_vkl_ACC znachenija_polzovatelia.PlanshBAT_timer_pri_vkl_ACC;
FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC znachenija_polzovatelia.FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC;
OTG_timer_pri_vkl_ACC znachenija_polzovatelia.OTG_timer_pri_vkl_ACC;
HUB_timer_pri_vkl_ACC znachenija_polzovatelia.HUB_timer_pri_vkl_ACC;
REGISTRATOR_timer_pri_vkl_ACC znachenija_polzovatelia.REGISTRATOR_timer_pri_vkl_ACC;
REM_timer_pri_vkl_ACC znachenija_polzovatelia.REM_timer_pri_vkl_ACC;
SLEEP_timer_pri_vkl_ACC znachenija_polzovatelia.SLEEP_timer_pri_vkl_ACC;
I_dva_C_szina_ON_time znachenija_polzovatelia.I_dva_C_szina_ON_time;
OTG_timer_pri_vykl_ACC znachenija_polzovatelia.OTG_timer_pri_vykl_ACC;
FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC znachenija_polzovatelia.FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC;
HUB_timer_pri_vykl_ACC znachenija_polzovatelia.HUB_timer_pri_vykl_ACC;
SLEEP_timer_pri_vykl_ACC znachenija_polzovatelia.SLEEP_timer_pri_vykl_ACC;
REM_timer_pri_vykl_ACC znachenija_polzovatelia.REM_timer_pri_vykl_ACC;
lcd_noBacklight_timer_pri_vykl_ACC znachenija_polzovatelia.lcd_noBacklight_timer_pri_vykl_ACC;
I_dva_C_szina_OFF_time znachenija_polzovatelia.I_dva_C_szina_OFF_time;
vremia_uderjanija_najatoj_knopki_POWER znachenija_polzovatelia.vremia_uderjanija_najatoj_knopki_POWER;
rezerv2 znachenija_polzovatelia.rezerv2;
rezerv3 znachenija_polzovatelia.rezerv3;
rezerv4 znachenija_polzovatelia.rezerv4;
rezerv5 znachenija_polzovatelia.rezerv5;
rezerv6 znachenija_polzovatelia.rezerv6;
rezerv7 znachenija_polzovatelia.rezerv7;
}    
//if znachenija_polzovatelia.reset_HUB_on_power_on)
    
//if (brac_nastrojki_iz_EEPROM == 2)
//0 - берём значения из скетча, игнорируя память ( кроме калибровки)
}//void RABOTA_z_EEPROM ()

void printDISPLAY() //функция формирования информации на дисплей ( точнее на два: 128*64 и 1602)
{
//_____________________________________________ФОРМИРУЕМ СООБЩЕНИЕ НА LCD ДИСПЛЕЙ____________________________________________________________

 
= (millis()/3600000);
 
= ((millis()-(H*3600000))/60000); 
//int S = (((millis()/1000)-(H*3600))- (M*60));
//if ((((millis())-(H*3600000))- (M*60000)) < 200 ){lcd.clear(); }//очистка дисплея
//int M = (millis()/60000); //минуты

 
if (flagACC == 1){lcd.backlight();}// для newE и для 0x27  
 // в 256 строке выключение подсветки LCD дисплея

 
 
 //пример: sprintf( strokaII,"SETUP volume on ");

//обработка 1й строки_________AKB ACC REM_____________________________________________________________________________________________________________________________________________________________________
 
sprintf(strokaI,"                ") ; 
                  
//IntToCharIIII((millis()/60000), &strokaI[0]); // вывод минут 0000 4 цифры СЕКУНД // если превысит 9999, то будут кроказябры!!! вида  ;0129
                  
IntToCharIII(H, &strokaI[0]);  // вывод часов 000 
                   
strokaI[3] =  ':'// вывод двоеточия 
                    
IntToCharII(M, &strokaI[4]);  // вывод минут 00 
                       
strokaI[7]= flagAKB '0';// вывод флага AKB 5 символ
                        
strokaI[8]= flagACC'0';// вывод флага AСС 6 символ
                         
strokaI[9]= REM '0';// вывод  rem 7 символ 1-усилок включен, 0 - выключен
                          
strokaI[10]= flagREM '0';// вывод  флага!!! rem 7 символ 1-усилок включен, 0,2 - выключен
                          
FloatToCharIIIII (U_acc_real,  &strokaI[11]);  // вывод напряжения АСС 
//конец обработки 1й строки ______________________________________________________________________________________________________________________________________________________________________________

//обработка 2й строки______________________________________________________________________________________________________________________________________________________________________________
 
TIMER = (  pauseTimeAKB  timeUntilALLOff millis()  )/60000// вывод кол-ва минут, оставшиеся до вЫключения блока (когда выключено АСС)


  // _______________________________Первые 30с после вкл -выкл ACC выводим версию блока.____________________________________________________________________________________________________________________________________________________
 
if (    ( millis()-pauseTimeACC  30000 )&& flagACC == 1   ){  sprintf(strokaII,"m__             ") ; IntToCharII(ver, &strokaII[1]);} else {  sprintf(strokaII,"____            ");   IntToCharIIII(TIMER, &strokaII[0]); } //Первые 30с после вкл -выкл ACC выводим версию блока
 // FloatToCharIIIII (rezerv7,  &strokaII[0]);
  // _____________________________________________________________________________________________________________________________________________________________________________________________________________________________________
 


//вывод OTG HUB POGO HALL
                      
strokaII[5]= STARTUEM '0';// 
                       
strokaII[6]= OTG '0';// вывод флага OTG 5 символ
                        
strokaII[7]= HUB '0';// вывод флага HUB 6 символ
                         
strokaII[8]= FIVE_Volt_OUT_na_POGO_or_USB '0';// вывод флага FIVE_Volt_OUT_na_POGO_or_USB (ПРИЗНАК ЗАРЯДКИ) 7 символ 
                           
strokaII[9]= !SLEEP '0';// вывод флага flagHALL 8 символ (инверсно)  1-экран включен, 0 - выключен
                               
FloatToCharIIIII (U_akb_real,  &strokaII[11]); // вывод напряжения АКБ
//конец обработки 2й строки ______________________________________________________________________________________________________________________________________________________________________________

if (kalibrovkaNOW >= && kalibrovkaNOW 255 )// если активен режим калибровки, то выводим данные для калибровки.
                      
{
                       
sprintf (strokaI,"                ") ; 
                       
IntToCharIII(Uacc,  &strokaI[0]);
                       
IntToCharIII(Uakb,  &strokaI[4]);
                       
IntToCharIII(kalibrovkaNOW, &strokaI[7]);  // вывод РЕЖИМА калибровки 
                       
                       
sprintf(strokaII,"c               ") ;
                       
IntToCharIII(kalibrovkaACC, &strokaII[1]);  // вывод значения калибровки АСС 
                       
IntToCharIII(kalibrovkaAKB, &strokaII[5]);  // вывод значения калибровки АСС 
                       
                       
FloatToCharIIIII (U_acc_real,  &strokaI[11]); // вывод напряжения АКБ
                       
FloatToCharIIIII (U_akb_real,  &strokaII[11]); // вывод напряжения АКБ

                      
}

//Вывод строк.______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
 
 
displayDataToDISPLAY(); //>>>>>>>>>>>>>> Сформировали строки, теперь надо их вывести на дисплеи:>>>>>>>>>>>>>> 
  



  /* так выглядит индикация на дисплее
  
   ================
  |000:00 111  0.000|          1 строка   *   вывод времени работы блока H:M                 *         AKB ACC REM            *    вывод напряжения АСС
  |2616  1110  14.50|    
   ================           2 строка   *   кол-во минут, оставшиеся до выключения блока    *         OTG HUB POGO HALL      *    вывод напряжения АКБ    
                                                                                               

*/
}

 
/******************************************конец индикации светодиодом и  вывода на дисплей********************************************************************************************************************************************************************************/
                                    

//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================

void analogReadU (byte averageFactor//функция усреднённого чтения аналоговых входов (A0 A1)
{//void analogReadU
  
int newUacc analogRead(PINrawACC);
  
int newUakb analogRead(PINrawAKB); 
 
   if (
averageFactor 0)        // усреднение показаний для устранения "скачков"
  
{      
    
Uacc = (Uacc * (averageFactor 1) + newUacc) / averageFactor;  
    
Uakb = (Uakb * (averageFactor 1) + newUakb) / averageFactor;  
    
// <новое среднее> = (<старое среднее>*4 + <текущее значение>) / 5 я тут немного поправил
  
} else {
    
Uakb=newUakb// не делаем усреднений, что прочитали то и считаем выводом
    
Uacc=newUacc// не делаем усреднений, что прочитали то и считаем выводом
  
}


}
//void analogReadU

void rejim_kalibrovki() //функция измерения, калибровки и записи полученных значений в еепром
{//void rejim_kalibrovki()
  
lcd.noBacklight();
  
delay (50);
  
lcd.backlight();
  
delay (250);
   if (
digitalRead(PINkalibrovki)== && kalibrovkaNOW 6)  {kalibrovkaNOW ++;} 
   else 
// тут достигли 6 касаний точки калибровки и ЗАПУСКАЕМ НЕПОСРЕДСТВЕННО ПРОЦЕСС КАЛИБРОВКИ ( ДЛЯ ЭТОГО ПОДАЁМ РОВНО 12,00В НА БЛОК ПИТАНИЯ ( асс и акб)
  
//else 
    
if (kalibrovkaNOW >= 6)
    {
//if (kalibrovkaNOW >= 6)
      
PORTBregistr 0// выключили всё
      
PORTDregistr 0// выключили всё 
      
UPRAVLENIE_PINAMI(); // сказали регистрам исполнить  " выключили всё ", вызвав функцию
      
delay (600); // для зарядки кондёров после снятия нагрузки
      
analogReadU (10); //вызов функции усреднённого чтения аналоговых входов - прочитали сырые данные с АЦП A0 и А1, потом их усреднили(10)раз
      
kalibrovkaACC 1200000/Uacc-1410// вычисляем значение калибровки, подав 12В на вход делителя U ( просто подключив питание к блоку питания)
      
kalibrovkaAKB 1200000/Uakb-1410// вычисляем значение калибровки, подав 12В на вход делителя U ( просто подключив питание к блоку питания) 
      
{kalibrovkaNOW ++;} 
    }
//if (kalibrovkaNOW >= 6)
  
}//else 
if ( kalibrovkaNOW == 15 &&  digitalRead(PINkalibrovki)== 0)   //по достижению счета в 254 и ПРИ МАССЕ НА ПИНЕ КАЛИБРОВКИ данные калибровки запишутся в еепром
                    
{
                      
kalibrovkaNOW 255;
                     
EEPROM.write(0,kalibrovkaACC);
                     
EEPROM.write(1,kalibrovkaAKB);
                      
                       
sprintf (strokaI,"end KALIBR.     ") ; 
                       
sprintf(strokaII,"c               ") ;
                       
IntToCharIII(kalibrovkaACC, &strokaII[1]);  // вывод значения калибровки АСС 
                       
IntToCharIII(kalibrovkaAKB, &strokaII[5]);  // вывод значения калибровки АСС 
                       
                       
FloatToCharIIIII (U_acc_real,  &strokaI[11]); // вывод напряжения АКБ
                       
FloatToCharIIIII (U_akb_real,  &strokaII[11]); // вывод напряжения АКБ
                      
displayDataToDISPLAY(); // 
                     
delay (10000);
                    
                     
                    }

}
//void rejim_kalibrovki()




void STATUS_REM() 
{
//void STATUS_REM() 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~обработка статуса выхода REM~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*если напруга батареи больше 12В, то включаем еще и усилитель звука (выход REM) /но включаем его только на  timeBeforeRemOff (30 минут), если не заведены.*/

    
if (U_akb_real >= UrabotyREM && flagACC == && flagREM == 0  ) {flagREM 1TimerREM millis();} //если подзаряжен акб и включили зажигание  - ВКЛЮЧАЕМ REM
    
if (U_akb_real >= UrabotyREM && flagACC == && ( millis() - TimerREM >= timeBeforeRemOff )) {flagREM ;}  //  если кончилось время обратного отсчета - статус рем - 2.
     //if (U_akb_real >= UnevykluczeniaREM && flagACC == 1){ (flagREM = 1);TimerREM = millis();} // если завели машину, - ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
    
if (U_akb_real >= UrabotyREM && flagREM == && flagACC == 0){ flagREM 0;} // если восстановилось напряжение при выключенном зажигании - обнуляем статус РЕМ.
    
if (U_akb_real <= UrabotyREM && flagACC == 1){ flagREM 2;} //если подсел акб при включенном зажигании - статус рем - 2.
      
if (U_akb_real >= UnevykluczeniaREM && flagACC == ){ (flagREM 1);TimerREM millis();} // если завели машину, - ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
       
if (U_akb_real >= UnevykluczeniaREM &&  flagREM == 3){ (flagREM 1);TimerREM millis();} // если завели машину, - ВКЛЮЧАЕМ REM, и постоянно обнуляем обратный отсчет вырубания РЕМ.
    
if (U_akb_real >= Uperezariadki){flagREM 2;}// проверка на перезаряд
    
if( flagREM == ||  flagREM == 2){REM 0;}  // выключаем выход REM
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~конец отработки выхода REM~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
}//void STATUS_REM() 


void obrabotka_ACC_ON() 
//START void obrabotka_ACC_ON() 
 //  ------------========================== блок ACC ========================-----------------------------------------------------------------------------


  //             -----------------=========ВКЛЮЧИЛИ ЗАЖИГАНИЕ=============---------------- 
  
if ((Uperezariadki U_acc_real) && (U_acc_real >= UaccONorOFF) && flagACC == && flagAKB == //проверка напруги АСС и АКБ при флаге ACC = 0
  
{
    
flagACC 1;
    
pauseTimeACC millis();
    
pauseTimeAKB millis();
    
  }

if (
U_acc_real >= UaccONorOFF)  //как только включили зажигание ( при любом напряжении батареи)


 if (
millis() - pauseTimeACC >= I_dva_C_szina_ON_time /* пауза XXX=I_dva_C_szina_ON_timec после появления напряжения на ACC и потом делать следующ(пока включено ACC):*/
        
{
            if (
razreszenie_raboty_I_dva_C_sziny  == 0// переопрашиваем дисплеи I2C и ставим флаг, чтобы они работали. 
      

             
//lcd.clear(); //очистка дисплея не нужна со строковым выводом
               
lcd.begin(162); //инициализация дисплея 1602 для newE библиотеки
         
sprintf(strokaI,"    INIT OK     ") ;
         
lcd.setCursor(00);
               
lcd.print(strokaI);
               
display2.begin(SSD1306_SWITCHCAPVCC0x3C);  // display 2 or adres 0x3D для 1306 дисплея
               
display2.clearDisplay();        // для 1306 дисплея
               
display2.setTextColor(WHITE);   // для 1306 дисплея
      // ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ТУТ надо будет включать питание на TDA7442 ! ! ! ! ! ! ! ! ! 
      
}
      
razreszenie_raboty_I_dva_C_sziny  1// разрешаем работу шины I2C 
      
        
}
               
        
// конец как только включили зажигание ( при любом напряжении батареи)
//} не нужна скобка


if (flagACC ==)
{
// если flagACC == 1
//проверить
      
if (((millis() - pauseTimeACC) >= (20)) )
      {
      if (
flagACC==&& flagAKB==1){STARTUEM 0;}  // определяем предположительный старт авто c задержкой XXXмс
      

//проверить      
  
if (millis() - pauseTimeACC >= PlanshBAT_timer_pri_vkl_ACC /* пауза 1.1c после включения ACC и потом делать следующ(пока включено ACC):*/
        
{
         
PlanshBAT 1;        //digitalWrite(PlanshBATpin, 1);  /*включаем питание на батарею планшета  = этим подаём 12В на DC-DC. На 1м канале dc-dc сразу появляется напряжение (3,8-4,2 - как настроено)*/ 
        
}
  
  if (
millis() - pauseTimeACC >= FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vkl_ACC /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
        
{
          
FIVE_Volt_OUT_na_POGO_or_USB 1;  //digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 1); /*включаем +5V (POGO(USB) нужно для распознавания планшетом признака зарядки. ( можно подавать на +5В USB кабеля (для тимуровской прошивки или если не используется датчик холла)*/
        
}
  
if (
millis() - pauseTimeACC >= OTG_timer_pri_vkl_ACC /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
       
{
         
OTG 1;              //digitalWrite(OTGpin, 1); /*включаем минус на OTG  (включается определение перифирии планшетом.)*/
       
}

if (
millis() - pauseTimeACC >= HUB_timer_pri_vkl_ACC /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
       
{
         
HUB 1;               //digitalWrite(HUBpin, 0); /*Включаем хаб = подаем минус на управляющий транзюк хаба, тот открывается и пускает +5В dc-dc (2вых)на хаб*/
       
}
                  
  if (
reset_HUB_on_power_on == 1)
  {
                  if (
millis() - pauseTimeACC >= (HUB_timer_pri_vkl_ACC+500) ) /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
                         
{
                           
HUB 0;               //digitalWrite(HUBpin, 1); /*Выключаем хаб*/
                         
}
                         
                  if (
millis() - pauseTimeACC >= (HUB_timer_pri_vkl_ACC+1000) ) /* пауза XXX после включения ACC и потом делать следующ(пока включено ACC):*/
                         
{
                           
HUB 1;               //digitalWrite(HUBpin, 0); /*Включаем хаб = подаем минус на управляющий транзюк хаба, тот открывается и пускает +5В dc-dc (2вых)на хаб*/
                         
}
  }
       
  if (
millis() - pauseTimeACC >= REGISTRATOR_timer_pri_vkl_ACC )/*через 2,2с после включения ACC включаем:  */
        
{
          
REGISTRATOR 1;// digitalWrite(REGISTRATORpin, 1); /* включаем питание  на видеорегистратор*/
          
if (millis() < 15000)  {flagREM =0;} // в первые 15 секунд при холодном пуске держим REM выключенным
      
if( flagREM == 1  && flagAKB == ){REM 1;} /* включаем выход REM*/
        
}

 if (
millis() - pauseTimeACC >= REM_timer_pri_vkl_ACC )/*через 2,2с после включения ACC включаем:  */
        
{
         if (
millis() < 15000)  {flagREM =0;} // в первые 15 секунд при холодном пуске держим REM выключенным
         
if( flagREM == 1  && flagAKB == ){REM 1;} /* включаем выход REM*/
        
}        

if (
HALL_as_power_Switch == 0)
//if (HALL_as_power_Switch == 0)
        
if (millis() - pauseTimeACC >= SLEEP_timer_pri_vkl_ACC // пауза  после включения ACC и потом делать следующ(пока включено ACC):
        
{SLEEP 0;} //digitalWrite(SLEEPpin, 0); /*включаем экран*/
//if (HALL_as_power_Switch == 0) 

if (HALL_as_power_Switch == 1)
{
//if (HALL_as_power_Switch == 1)
    
if (millis() - pauseTimeACC >= SLEEP_timer_pri_vkl_ACC )    {SLEEP 1;}//digitalWrite(SLEEPpin, 0); /*включаем экран*/
    
if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vkl_ACC+vremia_uderjanija_najatoj_knopki_POWER) ) { SLEEP 0;}
    
//if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vkl_ACC+1000) ) { SLEEP = 1;}
}//if (HALL_as_power_Switch == 1)
    
    
}// если flagACC == 1

STATUS_REM(); //зашли в функцию обработки статуса выхода REM

        
}//END void obrabotka_ACC_ON() 

void obrabotka_ACC_OFF()
//START obrabotka_ACC_OFF()
 //-----------------=========ВЫКЛЮЧИЛИ ЗАЖИГАНИЕ=============----------------
   

                                                            
  
if ((U_acc_real UaccONorOFF) && flagACC == 1)    
                                                {
                                                  
flagACC 0;  /*Выключили зажигание*/
                                                  
pauseTimeACC millis();
                                                  
pauseTimeAKB millis();
                                                }
 if (
flagACC==0)
 {
// if (flagACC==0)
  // 

  
if (((millis() - pauseTimeACC) >= (timeAfterACC-REM_timer_pri_vykl_ACC)) )  // тут REM_timer_pri_vykl_ACC (1000)- это на сколько раньше выключать выход REM перед остальными выключениями
                          
{
                          
REM 0;    //digitalWrite(REMpin, 0); // сразу выключаем усилитель звука
                          
flagREM 0/* выключаем флаг выхода REM*/ // обнуляем статус REM
                          
}
 
/*пауза 7c или 2c после вЫключения ACC и потом делать следующ://через 5с после выключения зажигания вЫключаем минус на OTG, ВЫключаем хаб, вЫключаем +5V (POGO(USB)), тушим экран (если прошло 2мин со старта БП)*/
  
  
if (((millis() - pauseTimeACC) >= (100)) )
      {
      if (
flagACC==&& flagAKB==0){STARTUEM 1;}  // определяем предположительный старт авто c задержкой XXXмс
      


if (
HALL_as_power_Switch == 0)
//if (HALL_as_power_Switch == 0)
      
if (((millis() - pauseTimeACC) >= (timeAfterACC+SLEEP_timer_pri_vykl_ACC)) ) 
                                                    {
                                                        if (
flagHALL == 1)
                                                                 {
SLEEP 1;}//digitalWrite(SLEEPpin, 1); /*тушим экран (если прошло 2 минуты с момента включения блока )*/
                                                            
else {SLEEP 0;}//{digitalWrite(SLEEPpin, 0);}
                                                    
}
//if (HALL_as_power_Switch == 0)                                                     
if (HALL_as_power_Switch == 1)
{
//if (HALL_as_power_Switch == 1)
    
if (millis() - pauseTimeACC >= SLEEP_timer_pri_vykl_ACC )    {SLEEP 1;}//digitalWrite(SLEEPpin, 0); /*включаем экран*/
    
if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vykl_ACC+HALL_as_power_Switch) ) { SLEEP 0;}
    
//if (millis() - pauseTimeACC >= (SLEEP_timer_pri_vykl_ACC+1000) ) { SLEEP = 1;}
}//if (HALL_as_power_Switch == 1)
    
                                                    
    
if ( ((millis() - pauseTimeACC) >=  (OTG_timer_pri_vykl_ACC+timeAfterACC))  ) /* 3000 пауза 3с чтобы не пукал усилитель*/
                                                            
{
                                                            
OTG 0;//digitalWrite(OTGpin, 0); /*вЫключаем минус на OTG (8 pin PW1)*/
                                                           
                                                            
}
    if ( ((
millis() - pauseTimeACC) >=  (FIVE_Volt_OUT_na_POGO_or_USB_timer_pri_vykl_ACC+timeAfterACC))  ) 
                                                            {
                                                            
FIVE_Volt_OUT_na_POGO_or_USB 0;//digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 0); /*вЫключаем +5V зарядки. (POGO(USB))*/
                                                            
}
 
    if ( ((
millis() - pauseTimeACC) >=  (HUB_timer_pri_vykl_ACC+timeAfterACC))  ) 
                                                            {
                                                             
HUB =0;//digitalWrite(HUBpin, 1); /* ВЫключаем хаб = подаем + на управляющий транзюк хаба, тот закрывается и не пускает +5В с KIW (2вых)на хаб*/
                                                            
}
                                                                                                                        
              
  if ( ((
millis() - pauseTimeACC) >=  (lcd_noBacklight_timer_pri_vykl_ACC+timeAfterACC))  ) 
                                                            {
                                                            
lcd.noBacklight();// тушим подсветку дисплея для newE и для 0x27 // в 409 строке включение подсветки LCD дисплея 
                                                            
}
                              
                              
    if  ( ((
millis() - pauseTimeACC) >=  (I_dva_C_szina_OFF_time timeAfterACC ))  && (razreszenie_raboty_I_dva_C_sziny  == 1) )  //когда вЫключили зажигание, по истечении времени (I_dva_C_szina_OFF_time) и если разрешение на работу I2C шины всё еще вЫключено - вЫключаем шину I2C
                                                            

                                                            
lcd.clear(); //очистка дисплея 
                                                            
razreszenie_raboty_I_dva_C_sziny  0//запрещаем работу I2C шины
                                                            // ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ТУТ надо будет вЫключать питание на TDA7442 ! ! ! ! ! ! ! ! ! 
                                                                
                                                            

    if ((
razreszenie_raboty_I_dva_C_sziny == 0) || (flagHALL ==1)) //Не даём заснуть первые 15с  
    
{Sleepy::loseSomeTime(vremia_sna_ATMEGI);}//  Т У Т   С П И М   sleep for XXX seconds   - когда запретили работу I2C шины, запускаем сон каждый цикл(loop) на 0,1 сек.                                                                                           

                                                            
 
}// if (flagACC==0)
       
//END obrabotka_ACC_OFF()


void obrabotka_AKB()
{
//START  obrabotka_AKB()
  //  -------------------------========================= блок контроля АКБ ==========================-------------------------------------------------------------------------------


if (U_acc_real >= UaccONorOFF)   {UakbONorOFF Uakb_Kogda_ACC_vkluczeno;}  else {UakbONorOFF Uakb_Kogda_ACC_vYkluczeno;} /*при включении зажигания напряжение самовырубания станет 11,1 вместо 11,9*/

  
if ((Uperezariadki U_akb_real) && ((U_akb_real >= UakbONorOFF) && flagAKB == 0)) /*проверка +30 на перезаряд >15.5В, и больше заданного в 266 строке, и флага акб */
    
{
      if ((
millis() - pauseTimeACC >= 100) && flagAKB == 0)
        {
        
SAMOZAPITKA =1;//digitalWrite(SAMOZAPITKApin, 1);  /* включаем самозапитку процессора        */
        
flagAKB 1/*подняли флаг батареи*/
        
}
    }
   
//Serial.print ("razreszenie_raboty_I_dva_C_sziny = "  ); Serial.println (razreszenie_raboty_I_dva_C_sziny);
 
if (((U_akb_real UakbONorOFF) && flagAKB == 1)||(U_akb_real >Uperezariadki))/* ситуация, когда сел при работе ардуины аккумулятор, либо сел в процессе работы или простоя автомобиля, либо перезарядка > 15.5В*/
    

      
flagAKB 0;//спустили флаг батареи
      
flagACC 0;
      
pauseTimeACC millis();
      
pauseTimeAKB millis();
      
UakbONorOFF Uakb_Kogda_ACC_vYkluczeno;
    }

  if ((
millis() - pauseTimeAKB >= timeWhileAkbLow) && flagAKB == 0/* если севший аккумулятор //через 40с вЫключаем питание на батарею планшета и вырубаем сам БП.*/
    
{    
      
PlanshBAT 0;          //digitalWrite(PlanshBATpin, 0);       /*вЫключаем питание на батарею планшета */
      
OTG 0;                //digitalWrite(OTGpin, 0);             /*вЫключаем минус на OTG )*/
      
FIVE_Volt_OUT_na_POGO_or_USB 0;    //digitalWrite(FIVE_Volt_OUT_na_POGO_or_USBpin, 0); /*вЫключаем +5V (POGO(USB))*/
      
HUB 0;                //digitalWrite(HUBpin, 1);             /* подаем + на управляющий транзюк хаба, тот закрывается и не пускает +5В с KIW (2вых)на хаб = ВЫключаем хаб*/
      
REM 0;                //digitalWrite(REMpin, 0);             /* выключаем выход REM*/
      
REGISTRATOR 0;        //digitalWrite(REGISTRATORpin, 0);     /* выключаем питание  на видеорегистратор*/
      
SAMOZAPITKA =0;         //digitalWrite(SAMOZAPITKApin, 0);     /*выключаем SAMOZAPITKApin, при этом пропадает управление на IN4, система ПОЛНОСТЬЮ обесточивается*/
      
UPRAVLENIE_PINAMI(); 
      
delay (5000);         // задержка для аппаратного выключения
    
}

  if (
flagAKB == && flagACC == 0)  /*ситуация, когда норм акб и выключено зажигание (ACC)*/
  
{
    if ((
millis() - pauseTimeAKB )>= timeUntilBATOff && flagAKB == 1)    /* если прошло "timeUntilBATOff" 24 (86400000) часа, как выключили ACC // пауза  (3600000 - 60мин) (60000 - 1 мин)(10800000=3ч) (1800000=5ч)*/
      

        
PlanshBAT 0;                                            // digitalWrite(PlanshBATpin, 0);  /*вЫключаем питание на батарею планшета (in2)//(батарея планшета))*/
      
}

    if ((
millis() - pauseTimeAKB) >= timeUntilALLOff && flagAKB == 1)   /* если давно выключили ACC     ) "timeUntilALLOff" (2суток = 172800000))     (самозапитка для регистратора, процессор БП активен)*/
      
REGISTRATOR 0//digitalWrite(REGISTRATORpin, 0);       /* выключаем питание  на видеорегистратор*/
        
SAMOZAPITKA 0;  //digitalWrite(SAMOZAPITKApin, 0);      /*выключаем SAMOZAPITKApin, при этом система ПОЛНОСТЬЮ обесточивается*/
        
UPRAVLENIE_PINAMI(); 
        
delay (10000);              // задержка для аппаратного выключения
      
}
  }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~конец блока обработки напряжений  АКБ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    
//END obrabotka_AKB()

void loop()
{while (
1){//для ускорения void loop
           
analogReadU (5);//вызов функции усреднённого чтения аналоговых входов - прочитали сырые данные с АЦП АКБ и АСС, потом их усреднили(5)раз.

if (kalibrovkaNOW != 255 && digitalRead(PINkalibrovki)== 0){if (  (millis() < 60000) || kalibrovkaNOW >= )  { rejim_kalibrovki();}      }  //    после 60с или если стоит ЗАПРЕТ(255), калибровку НЕ ДЕЛАЕМ



// новое ( с T12 версии)  вычисление реального напряжения, с учетом значений калибровки в еепром (0 и 1 адреса)
U_acc_real =  Uacc * (1410.0+kalibrovkaACC)/100000;
U_akb_real =  Uakb * (1410.0+kalibrovkaAKB)/100000;


 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ кусок кода ниже нужен для того, чтобы при включении  и сразу выключении ACC при полностью выключенном планшете(холодный старт) экран мог тухнуть по сигналу датчика холла.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  
if ( (millis() > pauseTimeHALL && flagHALL == )|| ((millis() > 15000) && flagACC == 1)) 
  {
flagHALL 1;} /*проверка отсчета при холодном старте при включении  и сразу выключении ACC*/
  /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~проверка, выключили ли мы зажигание или просто стартуем ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
if ((U_akb_real U_acc_real) >=)/*проверка, выключили ли мы зажигание или просто стартуем, нужно для того, чтобы не моргать экраном при стартере и быстро тушить экран при выключении зажигания.*/
          
{timeAfterACC timeAfterACC_accOFF; } //выключили зажигание.
     
else { timeAfterACC timeAfterACC_starting;     if (U_akb_real <=UakbONorOFF) {flagREM 3;REM 0;}   }//заводим машину (стартуем) или сел акб при включенном зажигании.
         
if (U_akb_real >= Uperezariadki){timeAfterACC 0;}


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/



  //  ------------========================== блок ACC ========================-----------------------------------------------------------------------------
obrabotka_ACC_ON(); // запустили блок обработки ACC (обработка режима включённого зажигания)
obrabotka_ACC_OFF(); // запустили блок обработки ACC (обработка режима вЫключенного зажигания)
 
  //  -------------------------========================= блок контроля АКБ ==========================------------------------------------------------------------------------------- 
obrabotka_AKB(); // запустили блок обработки АКБ

 



/******************************************индикация светодиодом и задержка вывода на дисплей********************************************************************************************************************************************************************************/
   
ms millis();
  
// Событие срабатывающее каждые 125 мс
  
if ( ( ms ms1 ) > 125 || ms ms1 ) {
    
ms1 ms;
    
// Режим светодиода ищем по битовой маске
    
if (  blink_mode << (blink_loop 0x07) ) {LED 1;}
    else { 
LED 0;}
    
blink_loop++;
  }
 
if (
razreszenie_raboty_I_dva_C_sziny  == 1// если разрешена работа для шины I2C 
{
  
// Событие срабатывающее каждые 350 мс
  
if ( ( ms pauseDisplay ) > vremia_obnovlenia_displeya || ms pauseDisplay 
  { 
   
pauseDisplay ms;
   
printDISPLAY(); // выводим на дисплей раз в 350( запуская фушкцию)
  
}
}  
  
  
 

 
/*настраиваем режимы моргания встроенного светодиода ардуины*/  
  
if (blink_mode != modes[5] || blink_mode != modes[5]) 
  {
  if (
flagAKB == ){blink_mode modes[4];}                 // индикация напруги батареи на ардуинине.- низкое напряжение АКБ авто - Две короткие вспышки раз в секунду 
  
if (flagAKB == && flagACC == 0) {blink_mode modes[3];} //- нормальное напряжение АКБ авто, ACC выключено.                     - Короткая вспышка раз в секунду
  
if (flagAKB == && flagACC == 1) {blink_mode modes[2];} //- нормальное напряжение, включено ACC, рабочий режим.                - Мигание по 0.8 сек
  
if (kalibrovkaNOW >= 1) {blink_mode modes[1];} // режим калибровки
      
  

 
/* ***********************данные для справки****************************************************************
    0B00000000, //Светодиод выключен blink_mode = modes[0]; 
    0B11111111, //Горит постоянно blink_mode = modes[1];      
    0B00111111, //Мигание по 0.8 сек  blink_mode = modes[2]; 
    0B00000001, //Короткая вспышка раз в секунду  = modes[3]; 
    0B00000101, //Две короткие вспышки раз в секунду 
    0B00010101, //Три короткие вспышки раз в секунду
    0B01010101  //Частые короткие вспышки (4 раза в секунду)= blink_mode = modes[6]; 
   */
//**********************************************************************************************************


//Serial.print ("HUB = "  ); Serial.println (HUB); 
if (STARTUEM == 1// когда крутим стартером ( заводимся) 
//если включено в настройках
    
if (power_off_HUB_on_starting == 1){HUB 0;} // выключаем питание на хаб в момент старта, если включено в настройках
    
if (power_off_OTG_on_starting ==1) {OTG 0;} // выключаем массу на OTG в момент старта, если включено в настройках
}

UPRAVLENIE_PINAMI(); 
 
//Sleepy::loseSomeTime(20);//  sleep for XXX seconds



}} /*конец цикла void loop() и конец while (1)*/
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
//===========================================================================================================================================================================================================================================================================
/* _
хотелки


______Сделано__________________________________________________
.
Контроль напряжения АКБ машины.
вывод информации на внешний дисплей по I2C,  библиотека вывода на экран https://github.com/enjoyneering/LiquidCrystal_I2C  и http://elchupanibrei.livejournal.com/27443.html
если в скетче в названии 0x27, значит библиотека старая.
активный вотчдог,
программная защита its716G(statepin)-тестово,
умное мигание встроенным светодиодом, в зависимости от напряжения АКБ и состояния АСС.
усреднение замеров по напряжению ACC и AKB, по 5 замерам.
информация на дисплее обновляется не постоянно, а каждые 350мс ( 0,35 с), чтобы не мельчешить.
Управление REM: если напруга батареи больше UrabotyREM (11.8 В), то включаем еще и усилитель звука (выход REM) /но включаем его только на 30-60мин, если не заведены. После заводки счетчик обнуляется.
v92 сделанъ плавный пуск - определяем нужное состояние пинов без их предварительного дергания в начальное нулевое.
v94 сделанъ вывод на экран через переменную, а не напрямую. ЭТО позволило выводить информацию ЕЩЕ И В КОМ ПОРТ!!! <<<<<<<========================================
v94 Сделана задержка включения REM после холодного запуска,  15с. Через 10 с после начала загрузки идёт инициализация звуковой, в этот момент слышен ПУК
t00 новая ветка блока, по факту продолжение старой.
t02 поскольку аптаймблока в машине превысил 9999 минут, то переделан вывод аптайма 000:00 ( часы : минуты)
t03 дисплей тухнет через 3 сек после операции завершения.
t04 добавлена поддержка дисплея Adafruit_SSD1306 128*64 (тестово). Библиотеки (2 штуки ): https://codeload.github.com/adafruit/Adafruit_SSD1306/zip/master
                   Без 2х библиотек одновременно работать не будет                    https://codeload.github.com/adafruit/Adafruit-GFX-Library/zip/master
t06 обработка напряжений выше 15,5 ( тушим экран и выключаем усилок)
t07 в войд сетап задержки по 0,1с для инициализации дисплеев. Изменен алгоритм выключения - сначала тушим экран, потом все остальное( для таскера, чтобы паузу ставил и плей жал)  
                        выключен Serial.print. display2.begin(SSD1306_ - перекинута инициализация на включение зажигания - 318 строка
t08- ничего
t09 - перенесена строка  проверки заведённой авто, в конец, перед проверкой перезаряда. 
t10 - перешел на другую библиотеку для 1602 дисплея( newE) https://github.com/enjoyneering/LiquidCrystal_I2C. 128*64 не проверял.
t11 - в связи с тем, что у меня дребезжит контактная группа в машине, изменён алгоритм выключения выхода REM 
t12 - возможность калибровки с записью в еепром, переделан метод вывода на дисплей ( теперь через две функции (формирования строк и непосредственно вывода.), а не в основном цикле), убрн вотчдог, как не имеющий практического смысла( пока что просто заккоментирован).
t13  поправлена Логика работы REM = когда стартуем flagREM = 3 Обработка логики работы REM в 538 строках.
t14 - введена новая переменная timeUntilBATOff = время до выключения питания на батарею планшета после выключения зажигания.  24ч = 86400000 (3600000 - 60мин) (60000 - 1 мин)(10800000=3ч) (1800000=5ч) (2суток = 172800000) (4суток = 345600000) 
                               timeUntilALLOff = время до полного выключение блока,  после выключения зажигания (ACC)  ((самозапитка для регистратора)- чтобы легче было менять это время в начале скетча.
      увеличено время поддержки планшета включённым-timeUntilBATOff ( 2 суток после выкл АСС и еще 2 суток после этого до полного выключения блока)    
                           
m01-05 - Новая версия БП5mini. Переход на новые, хорошо себя зарекомендовавшие, дс-дс (mini360). Датчик холла и отг теперь управляются специализированной микросхемой-твердотельным реле. Из-за неё же теперь потеряна совместимость прошивок на БП5 (поскольку на управление холлом теперь нужен инверсный сигнал).  Поэтому уже заодно поменял местами пины управления ОТГ и ХОЛЛА (физически). Фишка полностью совместима с БП5, БП4, БП3.
m6 - обработка статуса выхода REM переведена в отдельную функцию                           
m7 - поменян порядок включения элементов и их тайминги. Тестово. По идее, должно быть стабильнее, либо вообще никак не повлияет. Убраны лишние закомментированны строчки.
m11 - отг включаю сразу.
m12 - Сделал все основные тайминги настраиваемыми в начале скетча. Отдельно на включение, отдельно на выключение. Искать по строке ______НАСТРОЙКИ ТАЙМИНГОВ!!!______.
m14 - теперь тайминги в const unsigned long. В настройках скетча можно включить ресет хаба после каждого включения зажигания( reset_HUB_on_power_on )= передёргивать ли хаб при каждом включении зажигания, для решения проблемы с изикапом (STK1160) 1 - после ВКЛ АСС включить хаб, выключить на 0,5с и включить опять. 0 - просто включить хаб.
m15 - добавил тайминг timeWhileAkbLow = 40000; в настройки, увеличил с 20до 40с, для машин с функцией подсветки пути домой.    //время, через которое начнётся полное выключение блока когда напряжение на АКБ очень низкое. 
m18 - перевел все основные значения напряжений, таймингов и пинов на переменные.  Облегчение портирования на разные аппаратные платформы. ----> Подготовка совместимости с БП7.
m19 - более дружественные комментарии.
m20-22 - переписывание скетча, чтобы не выводить через I2C шину информацию, для экономии энергопотребления и совместимости с БП7. Изменены режимы моргания встроенного светодиода ардуины ( тоже даёт экономию при выключенном зажигании 0,005А). Добавлено время обновления I2C дисплея в настройках пользователя.
m23 - исправлено. иногда не выключалась самозапитка при севшем АКБ! теряется 1 байт в конце PORTBregistr. Поправил - пока стандартными командами в void UPRAVLENIE_PINAMI_BPV.
m24-26 - оптимизация кода и комментариев. 
m27 - добавлен спящий режим для атмеги при выключении зажигания. Уменьшено энергопотребление блока питания. когда запретили работу I2C шины, запускаем сон каждый цикл(loop) на 0,1 сек.                                                                                  ________________________________________________________________ 
m28 - перенесена обработка режимов АСС (вкл, вЫкл) в отдельнее функции. Добавлены настройки для пользователя ( выключать ли питание на хаб при кручении стартером, убирать ли массу с IDюсб = OTG при кручении стартером) 
m29 - добавлена задержка на определение, крутим ли мы стартером и прекратили ли крутить. Отдельной переменной не создавал, искать по переменной STARTUEM
m30 - добавлена возможность канал датчика холла подключать к физической кнопке питания планшета ( для тех, у кого нету датчика холла).
m31 - добавлена возможность писать свои некоторые персональные настройки в энергонезависимую память (EEPROM), подробнее в настройках пользователя и в void RABOTA_z_EEPROM (). 
m32 - Реализована возможность ВСЕ настройки пользователя писать в энергонезависимую память (EEPROM). Настройки НЕ совместимы с серсией m31, поэтому их надо переписать еще раз (brac_nastrojki_iz_EEPROM =1) 
добавлена настройка vremia_uderjanija_najatoj_knopki_POWER. уменьшено время сна атмеги с 100 до 50, на потребление не повлияло. 
 собственное потребление блока по 12 вольтам, без планшета (для БП5mini)
                                                    - при 10В +30 и +15 выключены                              = 0,014-0,017 А  ( меньше, если выпаять светодиоды с ардуины; также много из этого потребляет CH340G)
                                                    - при 12В +30 и +15 включены                               = 0,056-0,060 A
                                                    - при 12В +30 включены +15 выключены (при питании батареи) = 0,020-0,021 A
________________________________________________________________
поведение встроенного светодиода
    низкое напряжение АКБ авто                                         - коротко моргает
    нормальное напряжение АКБ авто, ACC выключено.                     - быстро моргает
    нормальное напряжение, включено ACC, рабочий режим.                - медленно моргает 


ПРИМЕЧАЕНИЯ
->  strcpy(strokaIIold,strokaII); // strokaIIold = strokaII; так нельзя!!! надо так:  strcpy(strokaIIold,strokaII); // копируем новую строку в старую 
*/ 
//Перед прошивкой скетча убедитесь в наличии нужных библиотек,например  d:\777\Soft\arduino\arduino-1.6.11\libraries\LiquidCrystal_I2C\  https://github.com/enjoyneering/LiquidCrystal_I2C например
//в версии T04 добавлена поддержка дисплея Adafruit_SSD1306 128*64  Библиотеки (2 штуки ): https://codeload.github.com/adafruit/Adafruit_SSD1306/zip/master  https://codeload.github.com/adafruit/Adafruit-GFX-Library/zip/master
//в версии m25 добавлена обязательная библиотека JeeLib library  https://github.com/jcw/jeelib .
// НЕДОСТАЮЩИЕ БИБЛИОТЕКИ СКАЧАТЬ И CКОПИРОВАТЬ В ПАПКУ libraries, например  d:\777\Soft\arduino\arduino-1.6.11\libraries\ . 
oleg707 вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.



Часовой пояс GMT +4, время: 07:47.


Работает на vBulletin® версия 3.8.4.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot