Бортовой компьютер для Опель Зафира.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Я имел ввиду попробовать новый код и сделать лог. Модернизировать старый код плохая затея он не оптимален и будет тормозить программу даже без задержки delay (100). Т. К. Он пытается принять все сообщение сразу за один проход луп. А без delay, возможно сообщение будет разрезано на 2 или более и тогда каша. Переделывать с новым кодом то минимум, формулы все те-же вставишь, только с номерами байт принятого сообщения немного подправить возможно придётся.

lev2606
Offline
Зарегистрирован: 19.06.2019

Макс, у меня в коде нет ни одного прерывания, поэтому изъятие байт из Serial-а прерываться не будет. И чем хорош твой код из 157 сообщения, я извлекаю байты из Serial-а не со скоростью 10400 бод, как он посылает, а с максимальной скоростью процессора(это примерно 50 мкСек на байт). Поэтому чтобы изъять все сообщение мне нужно будет не более 2 мСек! Этого даже энкодер не заметит!!!

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

lev2606
Offline
Зарегистрирован: 19.06.2019

ок, Макс, я попробую. Ты не обижайся, просто я не программист, я электронщик, и мне придется много времени потратить чтобы все собрать в одно по твоему новому варианту. Но я это обязательно сделаю! А пока проверю мою версию, сколько времени уходит на подпрограмму Recieve(). Макет БК собран, можно проводить полноценные эксперименты связи с ЭБУ. Кстати, я попробую твой новый код для начала отдельно, без интеграции в БК, так будет проще. Спасибо за помощь! ))) Машина Нексия N-150, с 16-ти клапанным двигателем и ЭБУ Sirius D42

MaksVV
Offline
Зарегистрирован: 06.08.2015

а че мне обижаться, это было скорее раздражение. я пытался тебе объяснить преимущества нового подхода, а ты мне про нет прерываний и что извлекаются байты из буфера уарт со скоростью процессора. А как быстро эти байты туда попадают? правильно, со скоростью 10400. весь ответ ЭБУ из 38 байт туда попадет примерно через 36 мс. как только первый байт туда попал, начинается работа функции receive() , поэтому задержка 100 мс и нужна чтобы дождаться остальные байты, ну или вариации были без нее , всё равно дожидаясь остальных байт функция работает, а это 36 мс. Не комильфо, я щитаю . То что попробуешь, это правильно. Если заработает, думаю лучше потратить время и перейти на новый вариант. 

lev2606
Offline
Зарегистрирован: 19.06.2019

вот засада! Не могу подключиться к ЭБУ! Новый распаянный макет не подключается, раньше подключался с макетом на штырьках- и все работало! У меня в новом макете даже все детали K-Line адаптера с того макета. Правда раньше была плата Uno, а теперь Mega. на Меге пробовал подключиться и с Serial2 и с SoftSerial (на те же выводы чтобы не перепаивать). Нет инициализации и все тут! Проверил работу адаптера- выдает и 0, и 1 (когда соответствующий сигнал на входе). Пробовал соединение ELM327 через блютуз на телефон-все работает, соединение с ЭБУ в норме! Аж остатки мозга закипели!!! ))) Шился скетчем из 157 поста, который раньше у меня работал и с него делал несколько логов. Вот такие дела!

lev2606
Offline
Зарегистрирован: 19.06.2019

опа, импульсный ИП на LM2576, вот где похоже собака-то! И К-Лайновский нагрузочный резистор надо уменьшить с 3,3 кОм до 510 Ом!

MaksVV
Offline
Зарегистрирован: 06.08.2015

если что,  на всякий скажу,  что разница  софтсериала и хардсериала есть, в контексте работы с к-линией. При работе через софтсериал отправленные байты НЕ прилетают обратно в приемник (эффекта эхо нет), а при работе через хардсериал прилетают (эффект эхо присутствует). Это надо учитывать в скетче. Не факт что причина у тебя в этом , но чтоб знал.  В скетче #2185 есть эта настройка (8 строка) . 

MaksVV
Offline
Зарегистрирован: 06.08.2015

lev2606 пишет:

Правда раньше была плата Uno, а теперь Mega. на Меге пробовал подключиться и с Serial2 и с SoftSerial (на те же выводы чтобы не перепаивать).

И ещё. На меге 2560 ноги, предназначенные для сериал2 не поддерживают softserial (точнее сказать Rx софт сериал), т. к. на них нет прерывания pcint.

lev2606
Offline
Зарегистрирован: 19.06.2019

спасибо, Макс! По правде говоря не знал этого. Ну что ж, попробую сериал3 с изначальным скетчем.

lev2606
Offline
Зарегистрирован: 19.06.2019

ну вот, наконец-то заработала связь с ЭБУ! Спасибо Максу! Заработало на сериале3 (14 и 15 выводы меги), но перед этим я пробовал на этих же выводах софт сериал - не стало работать, хотя на этих выводах pcint имеется! Ну и ладно, мне в общем-то сериал и нужен, чтобы прием данных происходил независимо от того, чем сейчас занимается процессор. Пришлось только буфер на 6 байт увеличить, чтобы еще и эхо принимать. Ну теперь уже можно полноценно опробовать макет БК! Завтра постараюсь устроить тест-драйв! ))). Вот лог с выключенным двигателем, но включенным зажиганием (с работающим двигателем лог не сохранился)

starting comunication (fastinit)
starting serial comunication
Zapros Initialization:  81  11  F1  81  4  
                                                        Recieve:   81 11 F1 81 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
Zapros Initialization:  81  11  F1  81  4  
                                                        Recieve:   81 11 F1 81 4 83 F1 11 C1 EF 8F C4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
                                                     Initialization OK!:  

PID delay:  150ms
Present delay:  9000ms

21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 68 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 9F 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
Zapros prisutstviya:   81  11  F1  3E  C1         9000ms
                                                        Recieve:   81 11 F1 3E C1 81 F1 11 7E 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
                                                        Recieve:   82 11 F1 21 2 A7 A2 F1 11 61 2 A5 71 0 6D 0 0 0 D3 FA D3 FA 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A4 
21-02:   82  11  F1  21  2  A7  
 

 

lev2606
Offline
Зарегистрирован: 19.06.2019

протестировал на БК, прикольно смотреть как повышается температура двигателя и изменяется напряжение бортовой сети! ))) Теперь нужно все доводить до ума. Кстати, посчитал что интервал опроса в 150 мСек маловат (со всеми интервалами по официальному протоколу) , возможны глюки. Поэтому увеличиваю интервал опроса до 200 мСек. Посмотрим как будут себя вести интервалы загрузки значков, экрана, меню, а главное не будет ли глючить энкодер!

MaksVV
Offline
Зарегистрирован: 06.08.2015

похоже я не дождусь проверки скетча #2185 ... 

lev2606
Offline
Зарегистрирован: 19.06.2019

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

не нужно интегрировать в свой проект, просто залей мой скетч и проверь. Для этого вроде не надо быть программистом.  

#define PCM_ADDRESS 0x11 // тут выбираем адрес ЭБУ для K-line
#define K_LINE Serial3   // тут выбираем Serial, на котором висит Клайн адаптер
#define TX 14            // и соответствующий ему  пин TX

#define PID_PERIOD_ms 250   // выбираем периодичность диагн запросов K-line
#define INIT_PERIOD_ms 25   // выбираем длительность импульсов fastinit K-line

#define HARDSERIAL_KLINE    // раскомментить, если Клайн адаптер подключен к железному Serial

#define DEBUG_KLINE  // раскомментить, если нужен дебаг сеанса клайн
//#define DEBUG_VALUES // раскомментить, если нужен дебаг параметров полученных по клайн

enum inita {NEED_INIT = 1, SENDED81 = 9, RECEIVED81, INIT_OK} ;
byte bus_init = NEED_INIT; 

const byte INIT []         {0x81};
const byte PIDS[][2]     {
                           {0x21, 0x02} // запрос диагностических параметров 
                           
};

#ifdef HARDSERIAL_KLINE
byte echo = 0; 
#endif
bool Timerreset = 0 ; 
uint32_t prevreset = 0; 
bool connectOK =0;   // флаг активно ли подключение к PCM

int8_t    Temper  = 0;
uint8_t Speed     = 0;
uint16_t N = 0;

 
void setup() 
{
#if defined DEBUG_KLINE or defined DEBUG_VALUES
  Serial.begin(115200);
#endif
delay(2000);
}

void sendMessage(const byte *command, const size_t size)
{
  if (!Timerreset) {Timerreset=1; prevreset = millis(); }// старт таймера контроля, что PCM на связи
  #ifdef DEBUG_KLINE 
  Serial.println(); Serial.print("               Send to PCM:  ");
  #endif
  const byte siZe = size+4;
  #ifdef HARDSERIAL_KLINE 
  echo = siZe;
  #endif
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) 
  {
    if (i==0) {Mes[i]=size; Mes[i]|=0x80;}
    if (i==1) Mes[i] = PCM_ADDRESS;
    if (i==2) Mes[i] = 0xF1;    
    if (i==3) {for (byte t=0; t<size; t++ ) 
        {Mes[i]=command[t]; Checksum+=Mes[i] ; 
        #ifdef DEBUG_KLINE 
        Serial.print(Mes[i],HEX); 
        Serial.print(" "); 
        #endif
        K_LINE.write (Mes[i]); //delay(1);  K_LINE.read(); 
        i++;}}
    if (i!=siZe-1) {Checksum+=Mes[i];}
    else {Mes[i] = Checksum;}    
    #ifdef DEBUG_KLINE 
    Serial.print(Mes[i],HEX); 
    Serial.print(" "); 
    #endif
    K_LINE.write (Mes[i]); //delay(1);  K_LINE.read(); 
  }
  #ifdef DEBUG_KLINE 
  Serial.println();
  #endif
}

void k_line()
{
  static byte header = 0;             // состояние заголовка 
  static byte message_size = 0;       // размер тела принимаемого сообщения, кол-во байт
  static byte j = 1;                  // инкремент
  static byte n = 3;
  const byte bufsize = 60;            // размер буфера принятого сообщения
  static byte buf [bufsize] = {0};    // буфер принятого сообщения
  static byte checksum = 0;           // контрольная сумма входящего сообщения
  static uint32_t prevRESETheader=0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались
  static bool RESETheader_timer = 0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались


static uint32_t timerInit = 0; 
     if (bus_init==NEED_INIT) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); bus_init++;}
else if (bus_init==2 && millis() - timerInit>INIT_PERIOD_ms) {timerInit = millis(); digitalWrite(TX, 1); bus_init++; }
else if (bus_init==3 && millis() - timerInit>INIT_PERIOD_ms) {K_LINE.begin (10400); 
                    #ifdef DEBUG_KLINE 
                    Serial.println("Fast init 25msLOW 25msHIGH");
                    #endif 
                    sendMessage (INIT, sizeof(INIT)); bus_init=SENDED81; }



if (K_LINE.available()){
  #ifdef HARDSERIAL_KLINE  
  if (echo>0){K_LINE.read(); echo--;return;}
  #endif
  
 // первый старт байт
 if (header == 0){buf[0]=K_LINE.read(); if (buf[0]!=0xFF && buf[0]!=0){
                                        #ifdef DEBUG_KLINE 
                                        Serial.print("Receive from PCM: "); Serial.print(buf[0],HEX); Serial.print(" "); 
                                        #endif
                                        header = 1; RESETheader_timer=1; prevRESETheader = millis();
                                                         }
                                        else {header = 0; RESETheader_timer=0;}
         
         }                  
 // второй старт байт
 else if (header == 1){buf[1]=K_LINE.read(); 
                       #ifdef DEBUG_KLINE 
                       Serial.print(buf[1],HEX);  Serial.print(" "); 
                       #endif
                       if (buf[1]==0xF1){ header = 2;} 
                       else {
                         #ifdef DEBUG_KLINE
                        Serial.println(" MessageReset"); 
                         #endif
                        header = 0; RESETheader_timer=0;}} 

 // третий старт байт
 else if (header == 2){buf[2]=K_LINE.read();
                        #ifdef DEBUG_KLINE 
                        Serial.print(buf[2],HEX); Serial.print(" ");  
                        #endif
     if (buf[2]==PCM_ADDRESS)
          { 
              if (buf[0] !=0x80 && buf[0] !=0xC0) {header = 4; message_size=buf[0]; message_size &=~0xC0; n=3;}
              else {header = 3; n=4;}
              if (message_size > bufsize) message_size = bufsize;  checksum = 0;
          } 
     else {
            #ifdef DEBUG_KLINE
            Serial.println(" MessageReset"); 
            #endif
            header = 0; RESETheader_timer=0; 
          }
  
                       }  
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){buf[3]=K_LINE.read(); 
                      #ifdef DEBUG_KLINE 
                      Serial.print(buf[3],HEX); Serial.print(" ");
                      #endif 
                      message_size = buf[3];
                      if (message_size > bufsize) {message_size = bufsize;}  
                      checksum = 0; header = 4;  
                     }

  // пишем тело сообщения 
 else if (header == 4 && j<= message_size+1) {
                      buf[j+n-1] = K_LINE.read(); 
                      #ifdef DEBUG_KLINE
                      Serial.print(buf[j+n-1],HEX);  Serial.print(" "); 
                      #endif 
                      if (j<message_size+1) {checksum+= buf[j+n-1];} // подсчёт КС
                      if (j==message_size+1) {header = 5; }
                      j++;
                      } 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {  

for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты

//for (byte i=0; i<message_size+n+1; i++) {if (buf[i]<=0xF)Serial.print ("0"); Serial.print (buf[i], HEX); Serial.print(" ");}


 // если контрольная сумма верна: 
if (buf[message_size+n] == checksum) 
 {
   prevreset = millis(); // сбрасываем таймер ресета , если получили валидное сообщение от блока
    #ifdef DEBUG_KLINE
    Serial.print("           CheckSUM good!" );
    #endif
    connectOK=1;
         if (buf[n]== 0xC1 && buf[n+1]==0xEF) {bus_init=INIT_OK;}
    
    else if (buf[n]== 0x61 && buf[n+1]==0x02)   {
                                         
                                         // тут  вставляем формулы
                                         
                                                } 
    
 }     
    
// если контрольная сумма не совпала: 
else {
       #ifdef DEBUG_KLINE
       Serial.print("           CheckSUM fail!!!" );
       #endif
     }

message_size = 0; header=0; RESETheader_timer=0; j=1; checksum = 0;
#ifdef DEBUG_KLINE
Serial.println();
#endif
 }
// таймер сброса заголовка если данные оборвались по середине сообщения
if (RESETheader_timer && millis() - prevRESETheader > 500)   
         {
         #ifdef DEBUG_KLINE
         Serial.println("timeout"); 
         #endif
         message_size = 0; RESETheader_timer = 0; header = 0;checksum = 0;j=1;
         }   
// таймер сброса диагностической сессии, если нет ответа от PCM более 5сек
if (Timerreset && millis() - prevreset>5000) {Timerreset = 0; bus_init=NEED_INIT; connectOK =0; }

//if (bus_init==RECEIVED81) {sendMessage (BEGIN, sizeof(BEGIN));bus_init=SENDED1086;} // отправка инита
static uint32_t prevtimePID = 0;
if (bus_init==INIT_OK && millis()-prevtimePID>PID_PERIOD_ms) {
     static byte piD = 0;
     prevtimePID= millis(); sendMessage (PIDS[piD],2);
     piD++; if (piD>=sizeof(PIDS)/2)piD=0;
     }
}

void DEBUGPrint()
{
 #ifdef DEBUG_VALUES
  static uint32_t prevdeb = 0; 
  if (millis()-prevdeb >500) {
     prevdeb = millis();
     Serial.print ("Speed="); Serial.print(Speed); Serial.print ("    T=");  Serial.print(Temper); 
     Serial.print("   N="); Serial.println(N);Serial.println();}
#endif 
}
 
void loop() 
{
k_line();     // опрос параметров по шине клайн
DEBUGPrint(); // отладка (отправка параметров в терминал)
}

 

lev2606
Offline
Зарегистрирован: 19.06.2019

Ок, попробую

MaksVV
Offline
Зарегистрирован: 06.08.2015

и скинь часть скетча где все формулы , я тебе их запихаю в свой скетч . дело 2х минут. потом в своём проекте удалишь все, что касается клайн . Вставишь в луп функцию k_line() и заинклюдишь файл "K_lineNexia_sirius.h" (я тебе в него упакую свой скетч), я думаю тогда у тебя  это не полгода займет, а несколько минут. 

lev2606
Offline
Зарегистрирован: 19.06.2019

спасибо, конечно... Хотя я и половины не понял чего ты написал! ))).Попробовал твой скетч #2215 работает, выкладываю Лог

lev2606
Offline
Зарегистрирован: 19.06.2019
16:46:55.737 -> ⸮Ҍ⸮BB@⸮⸮Fast init 25msLOW 25msHIGH
16:46:55.737 -> 
16:46:55.737 ->                Send to PCM:  81 11 F1 81 4 
16:47:00.798 -> Fast init 25msLOW 25msHIGH
16:47:00.798 -> 
16:47:00.798 ->                Send to PCM:  81 11 F1 81 4 
16:47:00.845 -> Receive from PCM: 83 F1 11 C1 EF 8F C4            CheckSUM good!
16:47:00.845 -> 
16:47:00.845 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:01.126 -> 
16:47:01.126 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:01.126 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 7A 0 4 89 CF 74 4C E 16 86 11 E2 5 E1 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 45            CheckSUM good!
16:47:01.360 -> 
16:47:01.360 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:01.407 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 73 0 4 81 CF 74 4C 21 16 81 11 E2 5 E0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 43            CheckSUM good!
16:47:01.594 -> 
16:47:01.594 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:01.641 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 78 0 4 84 CF 74 4C 5F 16 A2 11 E2 5 DE 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A8            CheckSUM good!
16:47:01.876 -> 
16:47:01.876 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:01.922 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 6E 0 4 85 CF 74 4C 44 16 95 11 E2 5 D3 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 6C            CheckSUM good!
16:47:02.110 -> 
16:47:02.110 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:02.157 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 78 0 4 8B CF 74 4C 33 16 89 11 E2 5 D2 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 5E            CheckSUM good!
16:47:02.391 -> 
16:47:02.391 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:02.391 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 70 0 4 8A CF 74 4B D2 16 6B 11 E2 5 C6 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 C9            CheckSUM good!
16:47:02.625 -> 
16:47:02.625 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:02.672 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 79 0 4 88 CF 74 4B F1 16 80 11 E2 5 C4 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 2            CheckSUM good!
16:47:02.860 -> 
16:47:02.860 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:02.906 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 73 0 4 8A CF 74 4C 9 16 7E 11 E2 5 BE 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 F            CheckSUM good!
16:47:03.141 -> 
16:47:03.141 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:03.188 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 79 0 4 8A CF 74 4B AC 16 5D 11 E2 5 B0 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 88            CheckSUM good!
16:47:03.375 -> 
16:47:03.375 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:03.422 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 6D 0 4 8A CF 74 4B 5D 16 54 11 E2 5 A9 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 1D            CheckSUM good!
16:47:03.609 -> 
16:47:03.609 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:03.656 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 7A 0 4 8C CF 74 4B 13 16 47 11 E2 5 A1 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 CD            CheckSUM good!
16:47:03.891 -> 
16:47:03.891 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:03.937 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 73 0 4 89 CF 74 4B 23 16 44 11 E2 5 99 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 C8            CheckSUM good!
16:47:04.125 -> 
16:47:04.125 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:04.172 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 78 0 4 80 CF 74 4B 58 16 51 11 E2 5 95 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 2            CheckSUM good!
16:47:04.406 -> 
16:47:04.406 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:04.453 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 6F 0 4 86 CF 74 4B 4C 16 48 11 E2 5 8E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E3            CheckSUM good!
16:47:04.640 -> 
16:47:04.640 ->                Send to PCM:  82 11 F1 21 2 A7 
16:47:04.687 -> Receive from PCM: A2 F1 11 61 2 4D 58 0 79 0 4 84 CF 74 4B 73 16 60 11 E2 5 8E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 2A 

 

lev2606
Offline
Зарегистрирован: 19.06.2019

Макс, разобрался в том, что ты мне написал, только один вопрос: про какие формулы идет речь? Формулы преобразования данных, получаемых через Клайн? и формулы расчета расхода топлива?

MaksVV
Offline
Зарегистрирован: 06.08.2015

Получаемых данных через клайн. Весь скетч выложи да и все.

lev2606
Offline
Зарегистрирован: 19.06.2019

Макс, у меня в проекте 9 файлов подпрограмм, не считая файлов с логотипом, значками и др. Если я эти 9 файлов просто соберу в один, то получится портянка длиной в 3000 строк! Попробую некоторые подпрограммы убрать или сделать пустыми.

MaksVV
Offline
Зарегистрирован: 06.08.2015

на яндекс диск всё положи и скинь ссылку 

lev2606
Offline
Зарегистрирован: 19.06.2019

https://disk.yandex.ru/d/uiiaedphciv0pA

Вот ссылка, вроде получилось закинуть на Яндекс Диск (первый раз делаю). К этому моменту уже удалось все что можно упаковать в один скетч

// Mega
// 09.10.2022г

#include <Adafruit_GFX.h>       // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#include <DS3231.h>

#include <FreeDefaultFonts.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSans18pt7b.h>

#define CLK 19
#define DT 18
#define SW 23    

#include "encMinim.h"
// пин clk, пин dt, пин sw, направление (0/1)
encMinim enc(CLK, DT, SW, 0);

#define K_LINE Serial3 

#define PROGMEM

// Подключение входов\выходов
#define TX_Pin          14      // выход команд на ЭБУ по OBD 
#define RX_Pin          15      // вход принимаемых данных от ЭБУ по OBD 
#define IGN_Pin         25      // вход зажигания - LOW при включении зажигания
#define Zapusk_Pin      27      // вход успешного запуска (с лампы заряда АКБ)
#define Gabarity_Pin    29      // вход индикации Габаритов - LOW при включении 
#define Bl_Svet_Pin     31      // вход включения ближнего света - LOW при включении света
#define Fuel_Switch_Pin 33      // вход переключения топлива бензин/газ
#define Encoder_But_Pin 23      // вход кнопки энкодера
#define KruiseOn_Pin    37      // вход индикации включения КК
#define KruiseGrab_Pin  35      // вход индикации подхвата КК
#define Kuler_Pin       41      // вход индикации включения Вентиллятора
#define China_Pin       39      // вход индикации спущенной Шины
#define Door_Pin        44      // вход дверей - LOW при открытых дверях
#define Lock_Door_Pin   46      // выход управления ЦЗ
#define PWM_Pin         45      // выход ШИМ - управления подсветкой дисплея
#define Power_Pin       47      // выход удержания питания
#define Temperature_Pin 24      // линия данных датчика внешней температуры 18b20
#define Tormoz_Pin      51      // вход выключателя стояночного тормоза
#define Revers_Pin      53      // вход выключателя задней передачи
#define Led_Pin         A5      // контакт дисплея, на который подается сигнал подсветки
#define Benzin_Pin      A8      // вход датчика уровня бензина (ДУТ)
#define Gaz_Pin         A9      // вход датчика уровня газа (ДУТ)
#define Speed_KK_Pin    A10     // вход датчика скорости аналоговый (псевдо)
#define Voltage_Pin     A11     // вход измерения напряжения АКБ
#define Temper_Dvig_Pin A12     // вход измерения температуры двигателя (псевдо)
#define Peredacha_Pin   A13     // вход переключения передач аналоговый (псевдо)

// настраиваемые параметры
byte BrightDAY = 255;             // яркость подсветки экрана ДНЕВНАЯ
byte BrightNIGHT = 120;           // яркость подсветки экрана НОЧНАЯ
byte SpeedDoorLock = 14;          // скорость, выше которой блокируются двери

DS3231 rtc(20, 21);               // Подключение RTC модуля (SDA, SCL)

// Предопределение основных цветов
#define BLACK       0x0000
#define RED         0xF800
#define GREEN       0x07E0
#define WHITE       0xFFFF
#define ORANGE      0xFD20      // оранжевый
#define ORANGE2     0xFBE0
#define BLUE        0x001F      // синий
#define GREENYELLOW 0xB7E0      // желто-зеленый 0xAFE5
#define DARKGREEN   0x03E0      // темно-зеленый
#define DARKGREY    0x2104      // темно-серый  7BEF
#define GREY        0x7BEF      // темно-серый  
#define CYAN        0x07FF      // голубой
#define MAGENTA     0xF81F      // фиалетовый
#define YELLOW      0xFFE0      // желтый
#define BROWN       0x99C2      // коричневый //A9E0
#define MAROON      0x7800
#define OLIVE       0x7BE0

#define BackGround BLACK

byte dataTime[4], prevTime[4];

unsigned int colorTemperature=DARKGREY;
unsigned int colorFuel=DARKGREY;   
unsigned int colorTextSpeed=DARKGREY;
unsigned int colorKruise=DARKGREY;
unsigned int colorDXO=DARKGREY;
unsigned int colorGabarity=BLACK;
unsigned int colorKuler=DARKGREY;
unsigned int colorChina=DARKGREY;
unsigned int colorFara=DARKGREY;
unsigned int colorSnow=DARKGREY;
unsigned int colorAuto=ORANGE;
unsigned int colorAKB=RED;
unsigned int colorTime=GREENYELLOW;
unsigned int colorDuga=GREY;
unsigned int colorScaleT=BLACK; 
unsigned int colorScaleB=BLACK; 

unsigned int TextColor = WHITE;     // цвет текста

int x1Scale, x2Scale, yScale;       // переменные для прорисовки шкал температуры и бензина
int xx, yy, xt ,yt;    // переменные для рисования кривых линий, разделяющих верхнюю и среднюю части экрана

bool fullStart = false;         // флаг полного запуска (соединение с ЭБУ при запущенном двигателе)
bool OnGabarity = false;
bool Podsvetka = false;
bool stateLight = false;
bool Connect = false;

byte pid = 1;               // очередность пида
bool Init = false;          // флаг успешного подключения к ЭБУ

byte PIDTime = 200;         // задержка между посылками запросов к ЭБУ, мс
byte waitbyte = 1;          // задержка между отправкой байт в сообщении, мс

byte hourLast=0;  
byte minLast=0;
byte secLast;

word VoltageAKB;
word BenzinVbake;
int Tdvig;
byte SpeedKruise=0;

int TemperatureOut=20;    // значение температуры

unsigned long startMillis = 0;  // предыдущая отсечка времени для отображения данных каждые 500 мСек

unsigned long previousMillis = 0;
unsigned long previousPID = 0;
unsigned long finishMillis = 0;
unsigned long variantMillis=0;
unsigned long dlitMillis;
unsigned long schetMin=0;

bool enabledPID = false;        // флаг запроса PID
bool enabledInit = false;       // флаг запроса инициализации

unsigned long currentPID=0;
unsigned long TimeInit;
unsigned long waitInit = 0;
unsigned long prevPID = 0;
unsigned long TimePID;
unsigned long waitPID = 0;
unsigned long timeReceive = 0;

byte n=0;
byte VolAKB;
byte VolAKB_H;
byte VolAKB_L;
float VoltAKB;
byte BenzinL;
byte GasL;
int ProbegSut=9999;
int PrevProbegSut=0;
byte ScreenBKvariant=0;

bool button_state = false;
bool button_long_state = false;
unsigned long ms_button = 0;

int xPosAuto;
int yPosAuto;
int xPosStation;
int yPosStation;
int xPosPoints;
int yPosPoints;
int xPosStrelka;
int yPosStrelka;
int xPosBenzin;
int yPosBenzin;

int ScaleT;               // шкала температуры ОЖ
byte ScaleB;              // шкала бензина в баке
int previousZnachT=0;     // предыдущее значение температуры
byte previousZnachB=0;    // предыдущее значение бензина
byte indexColorT=0;       // цвет значка температуры (синий, белый, красный)
byte indexColorB=0;       // цвет значка бензина (красный, белый, зеленый)
byte indexColorKk=0;      // цвет значка КК (серый,зеленый, красный)
byte indexColorSvet=0;    // цвет значка фары (серый, зеленый)

bool flagEndLogo=false;
bool flagDvigOn=false;
bool flagConnect=false;
bool flagProgrevDvig=false;
bool flagGab=false;
bool flagBliSvet=false;
bool flagOnPeredachaNo=true;
bool flagOnPeredacha1=false;
bool flagOnPeredacha2=false;
bool flagOnPeredacha3=false;
bool flagOnPeredacha4=false;
bool flagOnPeredacha5=false;
bool flagProbeg10km=false;
bool flagProbeg20km=false;
bool flagProbeg30km=false;
bool flagProbeg40km=false;

bool flagDXOon=false;
bool flagGabarityOn=false;
bool flagBligniySvetOn=false;
bool flagKruiseOn=false;
bool flagKruiseGrabOn=false;
bool flagKulerOn=false;
bool flagChinaOn=false;
bool flagSnowOn=false;
bool flagIconTemperature=false;
bool flagIconFuel=false;

int Znach[16];            // текущие значения 16-ти параметров
int previousZnach[16];    // предыдущие значения 16-ти параметров
int prevZnach[16];        // промежуточные значения 16-ти параметров

byte PeredachaN=0;        // номер передачи
bool Podhvat=false;       // флаг подхвата скорости КК
bool ZnakTdvig=false;     // знак температуры ОЖ

bool screenBK = true;         // true- экран БК/ false- экран Меню
bool screenStateBK = true;    // экран БК загружен после подпрограммы загрузки Start
bool screenStateMenu=false;   // экран Меню не загружен

bool obnovitValue[] = {         // флаги принудительного обновления 16-ти параметров
  true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true
};
bool obnovitValueT[] = {        // флаги принудительного обновления градаций шкалы температуры ОЖ
  true, true, true, true, true, true, true, true, true
};
bool obnovitValueB[] = {        // флаги принудительного обновления градаций шкалы бензина в баке
  true, true, true, true, true, true, true, true, true
};

bool obnovitProbSut[] = {true, true, true, true};   // флаги принудительного обновления цифр суточного пробега
bool obnovitTime[] = {true, true, true, true};      // флаги принудительного обновления цифр времени
bool obnovitTemperDvig[] = {true, true, true};      // флаги принудительного обновления цифр температуры ОЖ
bool obnovitSpeedKr[] = {true, true, true};         // флаги принудительного обновления цифр скорости подхвата КК
bool obnovitVoltAKB[] = {true, true, true};         // флаги принудительного обновления цифр напряжения АКБ
bool obnovitFuelB[] = {true, true};                 // флаги принудительного обновления цифр бензина в баке
bool obnovitFuelG[] = {true, true};                 // флаги принудительного обновления цифр газа в баке

int ECT = 0;               // температура ОЖ
int IAT = 0;               // температура на впуске
int TPS = 0;               // положение дроссельной заслонки
float VoltBS = 0;          // напряжение БС
byte Speed = 0;            // скорость
int RPM = 0;               // обороты двигателя
int BARO = 0;              // барометрическое давление
int MAP = 0;               // абсолютное давление
unsigned int MAF = 0;      // массовый расход воздуха
int InjDurSt = 0;          // длительность впрыска пусковая
float InjDur = 0;          // длительность впрыска текущая
unsigned int CorrInj = 0;  // коррекция длительности впрыска 
byte Gear = 0;             // передача МКПП
int FuelExt = 0;           // топлива в баке в литрах
int FuelExtPr = 0;         // топлива в баке в %
byte RealTPS = 0;          // реальное положение дроссельной заслонки

byte BrightLogarifm[] = {    // переменнная с логарифмическим изменением яркости светодиодов
  0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D, 0x1E, 0x1E, 0x1F, 0x20, 0x20, 0x21, 0x22, 0x23, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x3F, 0x41, 0x42, 0x44, 0x45, 0x47, 0x48, 0x4A, 0x4C, 0x4D, 0x4F, 0x51, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E, 0x60, 0x62, 0x64, 0x66, 0x69, 0x6B, 0x6D, 0x70, 0x72, 0x75, 0x77, 0x7A, 0x7C, 0x7F, 0x82, 0x85, 0x88, 0x8B, 0x8E, 0x91, 0x94, 0x97, 0x9B, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC9, 0xCD, 0xD2, 0xD6, 0xDB, 0xE0, 0xE5, 0xEA, 0xEF, 0xF4, 0xF9, 0xFF,
};

byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04};    // запрос инициализации  
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1};     // запрос присутствия    
byte messageRead[6] = {0x82,0x11,0xF1,0x21,0x02,0xA7};   // запрос 21 02

byte MessageRx[38] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};  //массив байтов принимаемого сообщения

const int Button[]={            // значения на аналоговом входе, соответсвующие нажатию 5-ти кнопок
  0, 322, 488, 588, 655
};

//-------------------------------[MENU]-----------------------------------------------------
const int TextSize     = 3;                      // Размер выводимых строк
const int FontWidth    = 6;                      // Ширина выводимых символов (Зависит от выбранного шрифта, стндартный = 5+1)
const int correctPosX  = FontWidth*TextSize;     // Вычисление позиции курсора в текстовых координатах: по оси X;

// Объявляем переменные
struct menu{                            // Структура, описывающая меню (шаблон)
  int Id;                               // Идентификационный уникальный индекс ID
  int parentId;                         // ID родителя
  bool isParam;                         // Является ли пункт изменяемым параметром
  String _Name;                         // Название
  int Value;                            // Актуальное значение
  int _Min;                             // Минимально возможное значение параметра
  int _Max;                             // Максимально возможное значение параметра
  int Koef;                             // длина названия
  int letArray;                         // длина массива
  int _Page;                            // номер страницы основного Меню
};

int menuArraySize = 43;                 // Задаем размер массива меню, всех используемых пунктов
unsigned long prevMillisMenu=0;         // предварительное значение в мСек для обработки нажатия кнопки

int hoursMenu;                          // переменная часов
int minuteMenu;                         // переменная минут
int secondsMenu;                        // переменная секунд

// Задаем пункты меню (объявляются структурные переменные)
menu Menus[]={                        // здесь (struct) можно не указывать
  {0, -1, false, "SETTING", 0, 0, 0, 7, 6, 0},                // УСТАНОВКИ
  {1, 0, false, "Time Current", 0, 0, 0, 12, 4, 1},           // Текущее время
  {2, 1, true, "Set Hours", hoursMenu, 0, 23, 9, 0, 1},       // Установка часов
  {3, 1, true, "Set Minute", minuteMenu, 0, 59, 10, 0, 1},    // Установка минут
  {4, 1, true, "Set Second", secondsMenu, 0, 59, 10, 0, 1},   // Установка секунд
  {5, 1, true, "Reset Second", 0, 0, 1, 12, 0, 1},            // Сброс секунд       
  {6, 0, false, "Point Travel", 0, 0, 0, 12, 1, 1},           // Путевая точка
  {7, 6, true, "Reset Point", 0, 0, 1, 11, 0, 1},             // Сброс данных путевой точки
  {8, 0, false, "Fuel Filling", 0, 0, 0, 12, 2, 1},           // Заполнение бака топливом
  {9, 8, true, "Set Petrol", 10, 0, 50, 10, 0, 1},            // Количество заливаемого бензина
  {10, 8, true, "Set Gas", 10, 0, 35, 7, 0, 1},               // Количество заполняющего газа
  {11, 0, false, "Display Light", 0, 0, 0, 13, 2, 1},         // Подсветка дисплея
  {12, 11, true, "Light DAY", 255, 0, 255, 9, 0, 1},          // Уровень дневной подсветки
  {13, 11, true, "Light NIGHT", 120, 0, 255, 11, 0, 1},       // Уровень ночной подсветки
  {14, 0, false, "Fuel Rate", 0, 0, 0, 9, 3, 1},              // Расход топлива
  {15, 14, true, "Rate /100 km", 0, 0, 30, 12, 0, 1},         // Расход на 100 км
  {16, 14, true, "Rate Instant", 0, 0, 1000, 12, 0, 1},       // Расход моментальный
  {17, 14, true, "Rate Travel", 0, 0, 1000, 11, 0, 1},        // Расход за поездку
  {18, 0, false, "Information", 0, 0, 0, 11, 2, 1},           // Информация
  {19, 18, true, "Read Info", 0, 0, 0, 9, 0, 1},              // Чтение информации
  {20, 18, true, "Reset Info", 0, 0, 1, 10, 0, 1},            // Сброс информации
  {21, 0, false, "DUT Calibrat", 0, 0, 0, 12, 5, 2},          // Калибровка датчика уровня топлива
  {22, 21, true, "Level 10 Litr", 200, 0, 1023, 13, 0, 2},    // Калибровка при 10 литрах в баке
  {23, 21, true, "Level 20 Litr", 400, 0, 1023, 13, 0, 2},    // Калибровка при 20 литрах в баке
  {24, 21, true, "Level 30 Litr", 600, 0, 1023, 13, 0, 2},    // Калибровка при 30 литрах в баке
  {25, 21, true, "Level 40 Litr", 800, 0, 1023, 13, 0, 2},    // Калибровка при 40 литрах в баке
  {26, 21, true, "Level 50 Litr", 1000, 0, 1023, 13, 0, 2},   // Калибровка при 50 литрах в баке
  {27, 0, false, "DUG Calibrat", 0, 0, 0, 12, 3, 2},          // Калибровка датчика уровня газа
  {28, 27, true, "Level 10 Litr", 200, 0, 1023, 13, 0, 2},    // Калибровка при 10 литрах в баке
  {29, 27, true, "Level 20 Litr", 400, 0, 1023, 13, 0, 2},    // Калибровка при 20 литрах в баке
  {30, 27, true, "Level 30 Litr", 600, 0, 1023, 13, 0, 2},    // Калибровка при 30 литрах в баке
  {31, 0, false, "Ubat Calibrat", 0, 0, 0, 13, 1, 2},         // Калибровка напряжения АКБ
  {32, 31, true, "Level 12v *10", 120, 0, 200, 13, 0, 2},     // Уровень при напряжении 12 вольт (*10)
  {33, 0, false, "Corr Injector", 0, 0, 0, 13, 1, 2},         // Коррекция впрыска
  {34, 33, true, "Pulse mS *10", 0, -100, 100, 12, 0, 2},     // Коррекция длительности импульса в мСек(*10)
  {35, 0, false, "Comm Interval", 0, 0, 0, 13, 4, 2},         // Установка интервалов связи с ЭБУ (в мСек)
  {36, 35, true, "Byte Transmit", 1, 0, 20, 13, 0, 2},        // межбайтовый интервал при запросе (через 1 мСек)
  {37, 35, true, "Byte Receiver", 1, 0, 20, 13, 0, 2},        // межбайтовый интервал при ответе ЭБУ(через 1 мСек)
  {38, 35, true, "Receiver ECU", 30, 25, 50, 12, 0, 2},       // интервал между запросом и ответом ЭБУ(через 1 мСек)
  {39, 35, true, "Transmit ECU", 200, 100, 5000, 12, 0, 2},   // интервал следующего запроса от ответа ЭБУ(через 100 мСек)
  {40, 0, false, "ECU Error", 0, 0, 0, 9, 2, 2},              // Сообщения об ошибках ЭБУ
  {41, 40, true, "Read Errors", 0, 0, 0, 11, 0, 2},           // Чтение ошибок 
  {42, 40, true, "Reset Errors", 0, 0, 1, 12, 0, 2}           // Сброс ошибок
};

int actualIndex = 0;              // текущий индекс Меню
bool isParamEditMode  = false;    // флаг режима редактирования параметра
int tmpValueMenu      = 0;        // переменная для хранения изменяемого параметра
int mMenu=0;                      // переменная массива Меню
 
int arrayMenu[7];           // массив возможных положений указателя текущего пункта меню
int strelkaArray=1;         // предпологаемое положение стрелки указателя текущего пункта меню
int prevStrelka=1;          // предыдущее положение стрелки указателя текущего пункта меню
int prevMainStrelka=1;      // предыдущее положение стрелки указателя пункта основного меню
int prevParentStrelka;      // предыдущее положение стрелки указателя пункта меню одного родителя
int setArrow=1;             // установка визуального положения стрелки указателя текущего пункта меню      


bool flagTimeMenu=true;     // флаг индикации времени
bool setStartMenu=true;     // флаг возвращения к старту Меню

unsigned int ColorLineMenu=RED;             // цвет линий контура Меню
unsigned int ColorCircleMenu=RED;           // цвет дуг контура Меню
unsigned int colorExitMenu=RED;             // цвет надписи Exit
unsigned int colorUkazatelEraseMenu=BLACK;  // цвет стирания указателя выбранного пункта Меню
unsigned int colorZamenaMenu=RED;           // цвет замены нового указателя Меню

int rcZamena=6;       // возможное предыдущее графическое положение указателя пункта Меню
int dMenu=-6;                 // величина сдвига рамки Меню
int nUkazatel=0;          // текущее графическое положение указателя пункта Меню
int previousZnachUn=-1;   // предыдущее графическое положение указателя пункта Меню
int maxStr=2;             // максимальное количество страниц на текущем уровне Меню
int prevMaxStr=1;         // максимальное количество страниц на предыдущем уровне Меню
int PageMenu=1;               // номер текущей страницы

bool obnovitValueUn[] = {        // массив флагов обновления положения указателя
  false, false, false, false, false, false
};

int ZnachMenu[4];             // массив переменных для обновления изменяемых значений
int previousZnachMenu[4];     // массив переменных предыдущих изменяемых значений
int prevZnachMenu[4];         // массив переменных для вычисления предыдущих изменяемых значений
int TavtoMenu;                // температура в автомобиле
bool ZnakTavtoMenu=false;     // знак температуры в автомобиле

byte hourLastMenu=0;          // установленные значения времени
byte minLastMenu=0;

int vmenu = 0;            // Переменная данных перемещения в Меню по вертикали
int hmenu = 0;            // Переменная данных перемещения по пунктам Меню (или изменение параметров)

bool obnovitTimeMenu[] = {true, true, true, true};  // массив флагов для обновления показания времени
bool obnovitTemperAvtoMenu[] = {true, true};        // массив флагов для обновления показания температуры в автомобиле

bool obnovitValueMenu[] = {         // массив флагов обновления переменных значений
  true, true, true, true
};

Time t;

//*******************************************************************************************************
void setup() {
  Serial.begin(115200);
  Serial.println("Test OK!");

         rtc.begin();

// Настраиваем входы\выходы устройства
    pinMode(RX_Pin, INPUT); 
    pinMode(TX_Pin, OUTPUT);     
    pinMode(IGN_Pin, INPUT_PULLUP);
    pinMode(Gabarity_Pin, INPUT_PULLUP);
    pinMode(Bl_Svet_Pin, INPUT_PULLUP);
    pinMode(Lock_Door_Pin, OUTPUT);
    pinMode(Power_Pin,OUTPUT);
    pinMode(PWM_Pin,OUTPUT);
    pinMode(Zapusk_Pin, INPUT_PULLUP);
    pinMode(KruiseOn_Pin, INPUT_PULLUP);
    pinMode(KruiseGrab_Pin, INPUT_PULLUP);
    pinMode(Kuler_Pin, INPUT_PULLUP);
    pinMode(China_Pin, INPUT_PULLUP);
    pinMode(Tormoz_Pin, INPUT_PULLUP);
    pinMode(Revers_Pin, INPUT_PULLUP);
    pinMode(Encoder_But_Pin, INPUT);
    pinMode(Led_Pin, INPUT);

    digitalWrite(Lock_Door_Pin, LOW);
    digitalWrite(Power_Pin, LOW);
    digitalWrite(PWM_Pin, HIGH);

    uint16_t ID;            // Инициализация экрана
    ID = tft.readID();
    tft.begin(ID);   

  tft.setRotation(1); 

  tft.fillScreen(BLACK);            // Устанавливаем цвет фона
        tft.setTextSize(2);

          StartBK(); 
}
//*******************************************************************************************************

void loop(){ 
      enc.tick();         // subDop, 85 str

      connectionECU();    // subDop, 1 str
        screenTrip();     // subDop, 37 str
        sensorsAvto();    // subDop, 98 str
        
    if(millis()-startMillis>500){
        startMillis=millis();
          BKreadData();
        t = rtc.getTime();
        TavtoMenu = rtc.getTemp();
    }     
        SetLight();       // subDop, 192 str          
}
//***************************************** END ********************************************************* 
void StartBK(){   
        SetLight();
      SetDisplay();
        showIconFara();
        t = rtc.getTime();
          BKreadData();
        if(digitalRead(Gabarity_Pin)==LOW && !stateLight){
              stateLight = true;
                colorGabarity=GREEN;
              showIconGabarity();
          for(byte i = BrightDAY; i > BrightNIGHT; i--){  // плавно понижаем яркость подсветки экрана в 3 раза
            analogWrite(PWM_Pin, BrightLogarifm[i]);
              delay(2);
          };  
        }else if(digitalRead(Gabarity_Pin)==HIGH && stateLight){
              stateLight = false;
              showIconFara();
          for(byte i = BrightNIGHT; i < BrightDAY; i++){
            analogWrite(PWM_Pin, BrightLogarifm[i]);         // плавно повышаем яркость подсветки экрана
              delay(2);
          };    
        }
          Obnovlenie();
          ObnovlenieT();   
          ObnovlenieB();

        fastInit();                            // подключение к ЭБУ

      digitalWrite(Power_Pin, HIGH);           // Включаем пин удержания питания
}
//*******************************************************************************************************
void connectionECU(){
    TimeInit = millis();
    TimePID = millis();
    currentPID = millis();
    
  if(!Init){                            // если нет инициализации,
    if(!enabledInit){                   // если флаг запуска инициализации опущен,
      waitInit = TimeInit;              // то запускаем таймер
      enabledInit = true;               // и поднимаем флаг запуска инициализации 
        Initialization();               // запрос инициализации
    }else{
      if((TimeInit - waitInit)>2000){   // задержка на ожидание ответа удачной инициализации, мс
        enabledInit = false;            // если нет ответа удачной инициализации, то опускаем флаг и прекращаем ожидание                                                      
      }                                 // чтобы снова повторить запрос инициализации
      if((TimeInit - waitInit)>100){
        Receive(12);
      }
    }      
  }else{
    if(!enabledPID){
      if((currentPID - prevPID) > 200 && (millis() - timeReceive) > 60){
          Zapros_2102(); 
        waitPID = TimePID; 
        enabledPID = true; 
        prevPID = currentPID;
      }
    }
    if(enabledPID){
      if((TimePID - waitPID)> 1000){   // задержка на ожидание ответа на PID, мс
        enabledPID = false;
      }
      if((TimePID - waitPID)> 100){
        Receive(44);
        timeReceive = millis();
      }
    }       
  }
}
//-----------------------------------------------------------------------------------------------------
void fastInit(){
    Serial.println("starting comunication (fastinit)");
  digitalWrite(TX_Pin, HIGH);     // makes K-line high
    delay(360);                    // wait for K-line to be clear
  digitalWrite(TX_Pin, LOW);      // makes K-line low
    delay(25);
  digitalWrite(TX_Pin, HIGH);     // makes K-line high
    delay(25);                     // last delay before first message
  K_LINE.begin(10400);             // baud rate of the OBD
    Serial.println("starting serial comunication");
}
//*******************************************************************************************************
void Initialization(){
    Serial.print("Zapros Initialization:  ");
  for(int i = 0; i < 5; i++){
    K_LINE.write(messageInit[i]);
      Serial.print(messageInit[i],HEX); 
      Serial.print("  ");
        delay(waitbyte);
  } 
        delay(30);
      Serial.println("");  
} 
//*******************************************************************************************************
void Zapros_2102(){
      Serial.print("21-02:   ");
    for(int i = 0; i < 6; i++){
      K_LINE.write(messageRead[i]);
        Serial.print(messageRead[i],HEX); 
        Serial.print("  ");
          delay(waitbyte); 
    } 
        Serial.println("");
}

void Receive(byte num){
  if(K_LINE.available()){
//        delay(100);
      byte k = 0;
      byte inbyte = 0;
    while(K_LINE.available() && k < num){
      inbyte = K_LINE.read();
      MessageRx[k] = inbyte;
        k++;
    }

      Serial.print("                                                        Recieve:   ");
    for(int i = 0; i < num; i++){
      Serial.print(MessageRx[i],HEX); 
      Serial.print(" ");
    } 
      Serial.println("");

    if(MessageRx[5]==0x83 && MessageRx[6]==0xF1 && MessageRx[7]==0x11 && MessageRx[8]==0xC1 && 
      MessageRx[9]==0xEF && MessageRx[10]==0x8F && MessageRx[11]==0xC4){
        Init = true;
        enabledInit = false;
        Serial.println("                                                     Initialization OK!:  "); 
    }
    if(MessageRx[6] == 0xA2 && MessageRx[7] == 0xF1 && MessageRx[8] == 0x11 && MessageRx[9] == 0x61 &&
        MessageRx[10] == 0x02){
          enabledPID = false;
          RashetInData();
    }
      for(byte i = 0; i < 44; i++) MessageRx[i] = 0;
  }
}

//*******************************************************************************************************
void RashetInData(){
  byte A = MessageRx[11];
  byte B = MessageRx[12];
  byte C = MessageRx[13];
  byte D = MessageRx[14];
  byte E = MessageRx[15];
  byte F = MessageRx[16];
  byte G = MessageRx[17];
  byte H = MessageRx[18];
  byte J = MessageRx[20];
  byte L = MessageRx[22];
  byte M = MessageRx[23];
  byte N = MessageRx[24];
  byte O = MessageRx[25];
  byte P = MessageRx[26];
  byte Q = MessageRx[27];
  byte T = MessageRx[30];
  byte U = MessageRx[31];
  byte V = MessageRx[32];
  byte Z = MessageRx[36];
  byte AC = MessageRx[39];

  ECT = A * 0.75 - 48.75;             // температура ОЖ, град С
  IAT = B * 0.75 - 48.75;             // температура на впуске, град С
  TPS = C * 0.392;                    // положение дроссельной заслонки, %
  VoltBS = (D - 40) / 5.6;            // напряжение БС, Вольт
  Speed = E;                          // скорость, км/ч
  RPM = F * 256 + G;                  // обороты двигателя, об/мин
  BARO = H * 0.465;                   // барометрическое давление, кПа
  MAP = J * 0.465;                    // абсолютное давление, кПа
  MAF = L * 5.44 + M / 47.00;         // массовый расход воздуха, мг/сек ?
  InjDurSt = (N * 256 + O) * 0.016;   // длительность впрыска пусковая, мс
  InjDur = (P * 256 + Q) * 0.004;     // длительность впрыска текущая, мс
  CorrInj = T * 256 + U;              // коррекция длительности впрыска, мс
  Gear = V;                           // передача МКПП
  FuelExt = Z * 0.196;                // топлива в баке, литр
  FuelExtPr = Z * 0.392;              // топлива в баке, %
  RealTPS = AC;                       // реальное положение дроссельной заслонки, шаг
}
//****************************************************************************************************************
void LockDoor(){ // функция запирания замков
  digitalWrite (Lock_Door_Pin, HIGH);
  delay (50);
  digitalWrite (Lock_Door_Pin, LOW);
}     
//*******************************************************************************************************
void PrintData(){
  tft.setCursor(0, 20);
  tft.print(utf8rus("температура ОЖ = "));
  tft.print(ECT);
  tft.print(" C");

  tft.setCursor(0, 40);
  tft.print(utf8rus("температура на впуске = "));
  tft.print(IAT);
  tft.print(" C");

  tft.setCursor(0, 60);
  tft.print(utf8rus("положение ДЗ = "));
  tft.print(TPS);
  tft.print(" %");

  tft.setCursor(0, 80);
  tft.print(utf8rus("напряжение БС = "));
  tft.print(VoltBS);
  tft.print(utf8rus(" В"));

  tft.setCursor(0, 100);
  tft.print(utf8rus("скорость = "));
  tft.print(Speed);
  tft.print(utf8rus(" км/ч"));

  tft.setCursor(0, 120);
  tft.print(utf8rus("обороты = "));
  tft.print(RPM);
  tft.print(utf8rus(" об/мин"));

  tft.setCursor(0, 140);
  tft.print(utf8rus("барометрическое давление  = "));
  tft.print(BARO);
  tft.print(utf8rus(" кПа"));

  tft.setCursor(0, 160);
  tft.print(utf8rus("абсолютное давление = "));
  tft.print(MAP);
  tft.print(utf8rus(" кПа"));

  tft.setCursor(0, 180);
  tft.print(utf8rus("масс расход воздуха = "));
  tft.print(MAF);
  tft.print(utf8rus(" мГр/Сек"));

  tft.setCursor(0, 200);
  tft.print(utf8rus("длит впрыска пусковая = "));
  tft.print(InjDurSt);
  tft.print(utf8rus(" мСек"));

  tft.setCursor(0, 220);
  tft.print(utf8rus("длит впрыска текущая = "));
  tft.print(InjDur);
  tft.print(utf8rus(" мСек"));

  tft.setCursor(0, 240);
  tft.print(utf8rus("корр длительности впрыска = "));
  tft.print(CorrInj);
  tft.print(utf8rus(" мСек"));

  tft.setCursor(0, 260);
  tft.print(utf8rus("передача МКПП = "));
  tft.print(Gear);
  tft.print("");

  tft.setCursor(0, 280);
  tft.print(utf8rus("топлива в баке = "));
  tft.print(FuelExt);
  tft.println(utf8rus(" литр"));

  tft.setCursor(0, 300);
  tft.print(utf8rus("реальное полож ДЗ = "));
  tft.print(RealTPS);
  tft.println(utf8rus(" шаг"));
}
//*******************************************************************************************************
void screenTrip(){
  if(screenBK == true){
    if(screenStateBK == false){
        screenStateBK = true;
        screenStateMenu = false;
        
      tft.fillScreen(BLACK);
      tft.setTextSize(2);
        flagDXOon=false;
 
      for(byte i=0; i<16; i++){ 
         obnovitValue[i]=true;
      }
      for(byte i=0; i<9; i++){ 
         obnovitValueT[i]=true;
      }
      for(byte i=0; i<9; i++){ 
         obnovitValueB[i]=true;
      }
      for(byte i=0; i<4; i++){ 
         obnovitProbSut[i]=true;
      }
      for(byte i=0; i<4; i++){ 
         obnovitTime[i]=true;
      }
      for(byte i=0; i<3; i++){ 
         obnovitTemperDvig[i]=true;
      }
      for(byte i=0; i<3; i++){ 
         obnovitSpeedKr[i]=true;
      }
      for(byte i=0; i<3; i++){ 
         obnovitVoltAKB[i]=true;
      }
      for(byte i=0; i<2; i++){ 
         obnovitFuelB[i]=true;
      }
      for(byte i=0; i<2; i++){ 
         obnovitFuelG[i]=true;
      }
        SetDisplay();
          iconStrelka();
          probegDigit();
          litrDigit();
          litrNaStoDigit();
          ostatokDigit();
          letterStroka(); 
    }
        if(enc.isClick()) SwitchScreenBK();   // переключение одометра и расходомера
        if(enc.isHolded()) screenBK = false;  // переход в Меню
        if(enc.isLeft());       // сброс боковых перемещений, не использующихся на экране БК
        if(enc.isRight());      // сброс боковых перемещений, не использующихся на экране БК

          Obnovlenie();
          ObnovlenieT();   
          ObnovlenieB();
  }else{
        TripMenu();
  }
}

void sensorsAvto(){
  if(digitalRead(Zapusk_Pin) == LOW){      

      if(!flagDXOon && digitalRead(Gabarity_Pin)==HIGH && digitalRead(Bl_Svet_Pin)==HIGH){    // если двигатель заведен, 
          flagDXOon=true;                           // и ДХО были отключены, тогда ДХО включаются
          flagGabarityOn=false;
          flagBligniySvetOn=false;
          indexColorSvet=1;           // ДХО включены
      }      
      if(!flagGabarityOn && digitalRead(Gabarity_Pin)==LOW && digitalRead(Bl_Svet_Pin)==HIGH){  // при включении Габаритов (LOW на входе)
          flagDXOon=false;
          flagGabarityOn=true;
          flagBligniySvetOn=false;
          indexColorSvet=2;           // Габариты включены
      }
      if(!flagBligniySvetOn && digitalRead(Bl_Svet_Pin)==LOW){        // при включении Ближнего Света (LOW на входе) 
          flagDXOon=false;
          flagGabarityOn=false;
          flagBligniySvetOn=true;
          indexColorSvet=3;           // Ближний свет включен
      }
      if(digitalRead(KruiseOn_Pin)==LOW && digitalRead(KruiseGrab_Pin)==HIGH){  // при включении КК (LOW на входе) 
          Podhvat=false;
          indexColorKk=1;
      }
      if(digitalRead(KruiseOn_Pin)==LOW && digitalRead(KruiseGrab_Pin)==LOW){     // при подхвате КК (LOW на входе)
          Podhvat=true;
          indexColorKk=2;
      }
      if(digitalRead(KruiseOn_Pin)==HIGH && digitalRead(KruiseGrab_Pin)==HIGH){     // при выключенном Круизе
          Podhvat=false;
          indexColorKk=0;
      }  
      if(digitalRead(KruiseOn_Pin)==HIGH && digitalRead(KruiseGrab_Pin)==LOW){     // при выключенном Круизе
          Podhvat=false;
          indexColorKk=0;
      }  
      if(digitalRead(Kuler_Pin)==LOW){        // при включении Вентиллятора (LOW на входе) 
          flagKulerOn=true;
        }else{
          flagKulerOn=false;
      }
      if(digitalRead(China_Pin)==LOW){        // при появлении сигнала спущенной Шины (LOW на входе) 
          flagChinaOn=true;
        }else{
          flagChinaOn=false;
      }
      if(TemperatureOut==0){                  // при переходе уличной темпереатуры через 0 
          flagSnowOn=true;
        }else{
          flagSnowOn=false;
      }

      if(Podhvat) SpeedKruise=Speed; 
      
      if(digitalRead(Tormoz_Pin)==LOW){           // ручник P
          PeredachaN = 8;
      }else if(digitalRead(Revers_Pin)==LOW){     // задний ход R
          PeredachaN = 7;
      }else if(digitalRead(Tormoz_Pin)==HIGH && digitalRead(Revers_Pin)==HIGH){
          PeredachaN = readKey();
      }
    }else{
      if(flagDXOon && digitalRead(Gabarity_Pin)==HIGH && digitalRead(Bl_Svet_Pin)==HIGH){
            flagDXOon=false;
            indexColorSvet=0;           // все выключено  
      }
      if(!flagGabarityOn && digitalRead(Gabarity_Pin)==LOW){  // при включении Габаритов (LOW на входе)
        flagDXOon=false;
        flagGabarityOn=true;
        flagBligniySvetOn=false;
        indexColorSvet=2;           // Габариты включены
      }
    }
}

void SwitchScreenBK(){
    ScreenBKvariant++;
    Serial.println("Switch Odometr");
      if(ScreenBKvariant>4) ScreenBKvariant=0;
        tft.fillRect(134, 78, 249, 34, BLACK);
              iconAuto();         // иконка автомобиля                     
              iconStation();      // иконка точки отсчета                  
              iconPoints();       // иконка точек прохождения               
              iconStrelka();
            for(byte p=0; p<4; p++){ 
               obnovitProbSut[p]=true;
            }              
              probegDigit();
              litrDigit();
              litrNaStoDigit();
              ostatokDigit();
              letterStroka();
}

void SetLight(){
  if(digitalRead(Gabarity_Pin)==LOW && !stateLight){
      stateLight = true;
    for(byte i = BrightDAY; i > BrightNIGHT; i--){  // плавно понижаем яркость подсветки экрана в 3 раза
      analogWrite(PWM_Pin, BrightLogarifm[i]);
        delay(2);
    };
  }else if(digitalRead(Gabarity_Pin)==HIGH && stateLight){
      stateLight = false;
    for(byte i = BrightNIGHT; i < BrightDAY; i++){
      analogWrite(PWM_Pin, BrightLogarifm[i]);         // плавно повышаем яркость подсветки экрана
        delay(2);
    };
  }
}
//--------------------------------[Меню]--------------------------------------------------
void TripMenu(){         
    vmenu = 0;      // Переменная хранящая действие по вертикали 1 - вход в меню, -1 - выход из меню
    hmenu = 0;      // Переменная хранящая действие по горизонтали 1 - вправо, -1 - влево

  if(screenStateMenu == false){
    screenStateMenu = true;
    screenStateBK = false;
    
      tft.fillScreen(BLACK);
      tft.setFont();
      tft.setTextSize(TextSize);      // Устанавливаем размер шрифта
      tft.setTextColor(RED, BLACK);   // Устанавливаем красный шрифт на чёрном фоне.
          actualIndex=0;
          strelkaArray=1;
          setArrow=1;
          PageMenu=1;
          setStartMenu=true;
      for(byte i=0; i<4; i++){ 
         obnovitTimeMenu[i]=true;
      }
      for(byte i=0; i<4; i++){ 
         obnovitValueMenu[i]=true;
      }
      for(byte i=0; i<2; i++){ 
         obnovitTemperAvtoMenu[i]=true;
      }  
        ShowMenu();      
  }
  
    if(enc.isClick()) vmenu = 1;
    if(enc.isHolded()) vmenu = -1;  
      
      ObnovlenieMenu();
  
    if(enc.isRight()){                   // если был поворот по часовой стрелке
      if(Menus[actualIndex].letArray == 1){
        hmenu = 0; 
      }else{
        hmenu = 1;         
      }
    }
    if(enc.isLeft()){                    // если был поворот против часовой стрелки
      if(Menus[actualIndex].letArray == 1){
        hmenu = 0; 
      }else{  
        hmenu = -1;  
      }
    }       
    if(vmenu != 0 || hmenu != 0) setActualMenu(vmenu, hmenu);  // Если было действие - реагируем на него    
}

void StartMenu(){
  if(setStartMenu){
    tft.setCursor(tft.width()/2-(correctPosX/2)*(Menus[actualIndex].Koef), 14);
      Serial.println("стартовое Меню");
    tft.print(Menus[actualIndex]._Name);
  }
          setStartMenu=false;
      for(int k=1; k < menuArraySize; k++){
        if(Menus[k].parentId == actualIndex && Menus[k]._Page == PageMenu){
            mMenu++;  
            arrayMenu[mMenu] = Menus[k].Id;
          if(mMenu == strelkaArray){   // 1
            nUkazatel = strelkaArray - 1;     // 0
              ObnovlenieUn();     // обновление Указателя
              tft.setTextColor(WHITE, BLACK);
            tft.setCursor(118, 35*mMenu+26); tft.print(Menus[k]._Name);  
          }else{ 
              tft.setTextColor(RED, BLACK); 
            tft.setCursor(118, 35*mMenu+26); tft.print(Menus[k]._Name); 
          }      
        }        
      }    
}

void Tochka1(){
  tft.fillRect(118, 60, 232, 200, BLACK);     // очистка меню
    StartMenu();
    RamkaCircleZamena();
}

void setActualMenu(int v, int h){
      mMenu=0;
// -----------------[Вертикальное перемещение]---------------------------------------
  if(h != 0){                            // Если горизонтальная навигация
        tft.setFont();
      tft.setTextSize(TextSize);      // Устанавливаем размер шрифта
      tft.setTextColor(WHITE, BLACK);
    if(Menus[actualIndex].isParam && isParamEditMode){  // В режиме редактирования параметра
        tmpValueMenu -= h;                    // Изменяем его значение и ...
                                // ... контроллируем, чтобы оно осталось в заданном диапазоне
      if(tmpValueMenu > Menus[actualIndex]._Max) tmpValueMenu = Menus[actualIndex]._Max;
      if(tmpValueMenu < Menus[actualIndex]._Min) tmpValueMenu = Menus[actualIndex]._Min;
        tft.fillRect(151, 61, 69, 22, BLACK);     // очистка поля изменяемого параметра
        tft.setCursor(151, 61); tft.print(tmpValueMenu);
          
    }else if(Menus[actualIndex].isParam && !isParamEditMode){
        tmpValueMenu = tmpValueMenu;
    }else{        
      // Если режим редактирования не активен, навигация среди потомков одного родителя  
           prevParentStrelka = strelkaArray; 
            setArrow = setArrow + h; 
          
      if(actualIndex == 0){
        if(setArrow > 12 && PageMenu == 2){
          setArrow = 1;
          PageMenu=1;
          rcZamena=5;
            Tochka1();
        }
        if(setArrow < 1 && PageMenu == 1){
          setArrow = 12;
          PageMenu=2;
          rcZamena=0;
            Tochka1();
        }
        if(setArrow < 7 && PageMenu == 2){
          PageMenu=1;
          rcZamena=0;
            Tochka1();
        }
        if(setArrow > 6 && PageMenu == 1){
          PageMenu=2;
          rcZamena=5;
            Tochka1();
        }  
        if(PageMenu == 1) strelkaArray=setArrow;
        if(PageMenu == 2) strelkaArray=setArrow-6;
      }else if(actualIndex >0){
        if(PageMenu == 1){
          if(setArrow > Menus[actualIndex].letArray) setArrow = 1;
          if(setArrow < 1) setArrow = Menus[actualIndex].letArray;
            strelkaArray=setArrow;
            clearStrelka();
        }
        if(PageMenu == 2){
          if((setArrow - 6) > Menus[actualIndex].letArray) setArrow = 7;
          if((setArrow - 6) < 1) setArrow = Menus[actualIndex].letArray + 6;
            strelkaArray=setArrow-6;
            clearStrelka();
        }
      }
          nUkazatel = strelkaArray - 1;
              ObnovlenieUn();
          tft.setTextColor(WHITE, BLACK);
        tft.setCursor(118, 35*strelkaArray+26); 
        tft.print(Menus[arrayMenu[strelkaArray]]._Name); 
              showTriangle(1);          // горизонтальное перемещение
      if(Menus[actualIndex].letArray > 1){        
          tft.setTextColor(RED, BLACK);
        tft.setCursor(118, 35*prevParentStrelka+26); 
        tft.print(Menus[arrayMenu[prevParentStrelka]]._Name);
      }
    }  
  }
// --------------------[Вход - Выход]-------------------------------------------              
  if(v != 0){               // Если вертикальный переход
        tft.setFont();
      tft.setTextSize(TextSize);      // Устанавливаем размер шрифта
      tft.setTextColor(RED, BLACK);
    if(v == -1){            // Команда ВВЕРХ (отмена)
      if(PageMenu == 1){                          //страница 1
        if(Menus[actualIndex].parentId ==0){      // если возврат в основное меню
          actualIndex =0;
          strelkaArray = prevMainStrelka;
          setArrow=strelkaArray;  //
          nUkazatel = strelkaArray-1;
        }else if(Menus[actualIndex].Id ==0){
              actualIndex = 0;
              strelkaArray=1;
              setArrow=1;
              screenBK = true;
                    return;
        }else{                                      // если возврат в подменю  
              strelkaArray = prevStrelka;
              setArrow=strelkaArray;  //
              nUkazatel = strelkaArray-1;
          if(Menus[actualIndex].parentId ==1) actualIndex =1;   
          if(Menus[actualIndex].parentId ==6) actualIndex =6;
          if(Menus[actualIndex].parentId ==8) actualIndex =8;
          if(Menus[actualIndex].parentId ==11) actualIndex =11;
          if(Menus[actualIndex].parentId ==14) actualIndex =14;
          if(Menus[actualIndex].parentId ==18) actualIndex =18;
        }
            isParamEditMode = false;
    }else if(PageMenu == 2){                    //страница 2
      if(Menus[actualIndex].parentId ==0){      // если возврат в основное меню
          actualIndex =0;
          strelkaArray = prevMainStrelka;
          setArrow=strelkaArray+6;
          nUkazatel = strelkaArray-1;
        }else if(Menus[actualIndex].Id ==0){
            actualIndex = 0;
            strelkaArray=1;
            setArrow=1;
            screenBK = true;
                  return;
              tft.fillScreen(BLACK);
        }else{                                      // если возврат в подменю
              strelkaArray = prevStrelka;
              setArrow=strelkaArray+6;
              nUkazatel = strelkaArray-1;
          if(Menus[actualIndex].parentId ==21) actualIndex =21;   
          if(Menus[actualIndex].parentId ==27) actualIndex =27;
          if(Menus[actualIndex].parentId ==31) actualIndex =31;
          if(Menus[actualIndex].parentId ==33) actualIndex =33;
          if(Menus[actualIndex].parentId ==35) actualIndex =35;
          if(Menus[actualIndex].parentId ==40) actualIndex =40;
        }
            isParamEditMode = false;     
      }
    }
    if(v == 1){             // Команда ВНИЗ (ввод)
      if(PageMenu == 1){
        if(Menus[actualIndex].Id == 0){     // вход из основного меню в подменю
          if(strelkaArray == 1) actualIndex=1;
          if(strelkaArray == 2) actualIndex=6;
          if(strelkaArray == 3) actualIndex=8;
          if(strelkaArray == 4) actualIndex=11;
          if(strelkaArray == 5) actualIndex=14;
          if(strelkaArray == 6) actualIndex=18;
              strelkaArray=setArrow;
              prevMainStrelka = strelkaArray;
        }else{                              // вход из подменю в настройки
          if(Menus[actualIndex].Id == 1){   // время
              
            if(setArrow == 1){          // часы
              actualIndex=2;
                t = rtc.getTime();
                hoursMenu = t.hour;
                minuteMenu = t.min;
                secondsMenu = t.sec;
              Menus[actualIndex].Value = hoursMenu;
            }
            if(setArrow == 2){          // минуты
              actualIndex=3;
                t = rtc.getTime();
                hoursMenu = t.hour;
                minuteMenu = t.min;
                secondsMenu = t.sec;
              Menus[actualIndex].Value = minuteMenu;
            }
            if(setArrow == 3){          // секунды
              actualIndex=4;
                t = rtc.getTime();
                hoursMenu = t.hour;
                minuteMenu = t.min;
                secondsMenu = t.sec;
              Menus[actualIndex].Value = secondsMenu;
            }
            if(setArrow == 4){          // секунды
              actualIndex=5;
                t = rtc.getTime();
                hoursMenu = t.hour;
                minuteMenu = t.min;
                secondsMenu = t.sec;
              Menus[actualIndex].Value = secondsMenu;
            }     
          }
          if(Menus[actualIndex].Id == 6){
            if(setArrow == 1) actualIndex=7;
          }
          if(Menus[actualIndex].Id == 8){
            if(setArrow == 1) actualIndex=9;
            if(setArrow == 2) actualIndex=10;
          }
          if(Menus[actualIndex].Id == 11){
            if(setArrow == 1) actualIndex=12;
            if(setArrow == 2) actualIndex=13;
          }
          if(Menus[actualIndex].Id == 14){
            if(setArrow == 1) actualIndex=15;
            if(setArrow == 2) actualIndex=16;
            if(setArrow == 3) actualIndex=17;
          }
          if(Menus[actualIndex].Id == 18){
            if(setArrow == 1) actualIndex=19;
            if(setArrow == 2) actualIndex=20;
          } 
                strelkaArray=setArrow;
          if(!isParamEditMode) prevStrelka = strelkaArray;  // запоминаем позицию стрелки, 
                                                            // если не изменяем параметр
      }                                                     
          if(!Menus[actualIndex].isParam) strelkaArray =1;  // при вводе позиция стрелки=1, кроме
              setArrow=strelkaArray; 
              nUkazatel=0;                                 // перехода в редактируемые параметры
    }else if(PageMenu == 2){
            strelkaArray =setArrow-6;
        if(Menus[actualIndex].Id == 0){     // вход из основного меню в подменю
          if(strelkaArray == 1) actualIndex=21;
          if(strelkaArray == 2) actualIndex=27;
          if(strelkaArray == 3) actualIndex=31;
          if(strelkaArray == 4) actualIndex=33;
          if(strelkaArray == 5) actualIndex=35;
          if(strelkaArray == 6) actualIndex=40;
              prevMainStrelka = strelkaArray;
        }else{                              // вход из подменю в настройки
          if(Menus[actualIndex].Id == 21){
            if(strelkaArray == 1) actualIndex=22;
            if(strelkaArray == 2) actualIndex=23;
            if(strelkaArray == 3) actualIndex=24;
            if(strelkaArray == 4) actualIndex=25;
            if(strelkaArray == 5) actualIndex=26;
          }
          if(Menus[actualIndex].Id == 27){
            if(strelkaArray == 1) actualIndex=28;
            if(strelkaArray == 2) actualIndex=29;
            if(strelkaArray == 3) actualIndex=30;
          }
          if(Menus[actualIndex].Id == 31){
            if(strelkaArray == 1) actualIndex=32;
          } 
          if(Menus[actualIndex].Id == 33){
            if(strelkaArray == 1) actualIndex=34;
          }
          if(Menus[actualIndex].Id == 35){
            if(strelkaArray == 1) actualIndex=36;
            if(strelkaArray == 2) actualIndex=37;
            if(strelkaArray == 3) actualIndex=38;
            if(strelkaArray == 4) actualIndex=39;
          }
          if(Menus[actualIndex].Id == 40){
            if(strelkaArray == 1) actualIndex=41;
            if(strelkaArray == 2) actualIndex=42;
          }
            if(!isParamEditMode){ 
              prevStrelka = strelkaArray;   // запоминаем позицию стрелки,
                                            // если не изменяем параметр
            }
                                                              
        }                                                     
            if(!Menus[actualIndex].isParam){ 
              strelkaArray =1;              // при вводе позиция стрелки=1, кроме
              nUkazatel=0;                 // перехода в редактируемые параметры
            }
                  setArrow=strelkaArray+6;                                                                        
      }
    }
// -----------------------[Отображение Подменю]---------------------------------------
        tft.fillRect(120, 13, 240, 24, BLACK);         // очистка заголовка
          tft.setFont();
          tft.setTextSize(TextSize);
        tft.setCursor(tft.width()/2-(correctPosX/2)*(Menus[actualIndex].Koef), 14);  
        tft.print(Menus[actualIndex]._Name);        // текущее название заголовка
          tft.fillRect(117, 59, 235, 200, BLACK);     // очистка меню
          
            if(actualIndex == 0 && maxStr == 1){
                maxStr=2;
              if(PageMenu != prevMaxStr) obnovitValueMenu[2]=true;  
            }else if(actualIndex > 0 && maxStr == 2){
                maxStr=1;
            }
  
              clearTriangle();
        if(!Menus[actualIndex].isParam){    // печать меню элементов без измененяемых параметров
          for(int k=0; k < menuArraySize; k++){
            if(Menus[k].parentId == actualIndex && Menus[k]._Page == PageMenu){
                mMenu++;
                arrayMenu[mMenu] = Menus[k].Id;// 
              if(mMenu == strelkaArray){
                nUkazatel=strelkaArray-1;
                  clearStrelka();
                previousZnachUn=-1;
                  ObnovlenieUn();
                tft.setTextColor(WHITE, BLACK);
                tft.setCursor(118, 35*mMenu+26); tft.print(Menus[k]._Name);
              }else{
                tft.setTextColor(RED, BLACK); 
                tft.setCursor(118, 35*mMenu+26); tft.print(Menus[k]._Name); 
              }      
            }      
          }
        }else{                // печать меню элементов с измененяемыми параметрами
          if(Menus[actualIndex].isParam && !isParamEditMode){   // Если не в режиме редактирования, то ...
            isParamEditMode = true;                           // Переходим в режим редактирования параметра
            tmpValueMenu = Menus[actualIndex].Value;    // Временной переменной присваиваем актуальное значение параметра
                clearStrelka();
              tft.setTextColor(WHITE, BLACK);
            tft.setCursor(118, 61); tft.print(">");
            tft.setCursor(151, 61); tft.print(tmpValueMenu);
              tft.setTextColor(RED, BLACK);
            tft.setCursor(118, 96); tft.print("min: " + (String)Menus[actualIndex]._Min);
            tft.setCursor(118, 131); tft.print("max: " + (String)Menus[actualIndex]._Max);
            
          }else if(Menus[actualIndex].isParam && isParamEditMode){  // Если в режиме редактирования
              Menus[actualIndex].Value = tmpValueMenu;              // Сохраняем заданное значение
            if(actualIndex == 2){
              hoursMenu = tmpValueMenu;
              rtc.setTime(hoursMenu, minuteMenu, secondsMenu);
            }
            if(actualIndex == 3){
              minuteMenu = tmpValueMenu;
              rtc.setTime(hoursMenu, minuteMenu, secondsMenu);
            }
            if(actualIndex == 4){
              secondsMenu = tmpValueMenu;
              rtc.setTime(hoursMenu, minuteMenu, secondsMenu);
            }
            if(actualIndex == 5){
              secondsMenu = tmpValueMenu;
              rtc.setTime(hoursMenu, minuteMenu, secondsMenu);
            }
              isParamEditMode = false;                 // И выходим из режима редактирования 
                tft.setTextColor(WHITE, BLACK);
              tft.setCursor(118, 61); tft.print(":");
              tft.setCursor(151, 61); tft.print(Menus[actualIndex].Value);
          }
        }
                showTriangle(0);    // вертикальное перемещение
  }
}
// ------------------------------[Время]------------------------------------------------
void timeBoxMenu(){
      tft.setTextColor(WHITE);
    tft.fillRect(321, 291, 2, 2, WHITE); 
    tft.fillRect(321, 300, 2, 2, WHITE); 

    if(t.min!=minLastMenu){
        prevTime[0]= hourLastMenu /10;
        prevTime[1]= hourLastMenu %10;
        prevTime[2]= minLastMenu /10;
        prevTime[3]= minLastMenu %10;

        dataTime[0]= t.hour /10;
        dataTime[1]= t.hour %10;
        dataTime[2]= t.min /10;
        dataTime[3]= t.min %10;
        
          hourLastMenu = t.hour;
          minLastMenu = t.min;      
    }

      for(byte tm=0; tm<4; tm++){
        if (dataTime[tm]!=prevTime[tm] || obnovitTimeMenu[tm]) {
                obnovitTimeMenu[tm]=true;
            switch (tm) {              
                case 0:      
                    if(obnovitTimeMenu[tm]){                // 10
                        obnovitTimeMenu[tm]=false;
                          tft.fillRect(294, 287, 11, 17, BLACK);
                        if(hourLastMenu > 9)showmsg1XY(293, 303, 1, &FreeSans12pt7b, dataTime[tm]);      // часы десятки
                    }
                    break;
                case 1:      
                    if(obnovitTimeMenu[tm]){                // 1
                        obnovitTimeMenu[tm]=false;
                          tft.fillRect(307, 287, 11, 17, BLACK);
                        showmsg1XY(306, 303, 1, &FreeSans12pt7b, dataTime[tm]);    // часы единицы   
                    }
                    break;
                case 2:      
                    if(obnovitTimeMenu[tm]){                // 10
                        obnovitTimeMenu[tm]=false;
                          tft.fillRect(326, 287, 11, 17, BLACK);
                        showmsg1XY(325, 303, 1, &FreeSans12pt7b, dataTime[tm]);   // минуты десятки
                    }  
                    break;
                case 3:       
                    if(obnovitTimeMenu[tm]){                // 1
                        obnovitTimeMenu[tm]=false;
                          tft.fillRect(339, 287, 11, 17, BLACK);
                        showmsg1XY(338, 303, 1, &FreeSans12pt7b, dataTime[tm]);   // минуты единицы 
                    }
                    break;
            }
        }
      }    
}
// -----------------------------[Температура в авто]-------------------------------------
void temperatureAvtoMenu(){
    byte TemperAvto[2], prevTemperAvto[2];             // 123

      tft.setTextColor(WHITE);
  showmsgXY(160, 295, 1, &FreeSans9pt7b, "o");
  showmsgXY(172, 303, 1, &FreeSans9pt7b, "C");

  if(TavtoMenu >= 0){       
      ZnakTavtoMenu= true;           // +
  }else if(TavtoMenu < 0){        
      ZnakTavtoMenu= false;          // -
  }
  
        prevTemperAvto[0]= prevZnachMenu[0] /10;          // 1
        prevTemperAvto[1]= abs(prevZnachMenu[0]) %10;     // 2

        TemperAvto[0]= ZnachMenu[0] /10;
        TemperAvto[1]= abs(ZnachMenu[0]) %10;

      for(byte ta=0; ta<3; ta++){
        if (TemperAvto[ta]!=prevTemperAvto[ta] || obnovitTemperAvtoMenu[ta]) {
                obnovitTemperAvtoMenu[ta]=true;
            switch (ta) {
                case 0:      
                    if(obnovitTemperAvtoMenu[ta]){                // 10
                        obnovitTemperAvtoMenu[ta]=false;
                          tft.fillRect(131, 287, 11, 17, BLACK);
                        if(ZnachMenu[0] >9)showmsg1XY(130, 303, 1, &FreeSans12pt7b, TemperAvto[ta]);   // byte
                    }   
                    break;
                case 1:       
                    if(obnovitTemperAvtoMenu[ta]){                // 1
                        obnovitTemperAvtoMenu[ta]=false;
                          tft.fillRect(144, 287, 11, 17, BLACK);
                        showmsg1XY(143, 303, 1, &FreeSans12pt7b, TemperAvto[ta]);
                    }
                    break;
            }
        }
      }    
}
// ---------------------------------[ END ]--------------------------------------------
void clearStrelka(){
  for(rcZamena=0; rcZamena<=5; rcZamena++){
    RamkaCircleZamena();  // 88
  }
}

void ObnovlenieMenu(){
  for(byte i=0; i<=3; i++){
    switch (i) {  // вывод на экран в первой строке выбранного параметра
        case 0:       // температура в салоне автомобиля
              ZnachMenu[i] = TavtoMenu;
            break;
        case 1:       // Время
              ZnachMenu[i] = t.min;
            break;
        case 2:         // текущая страница Меню
              ZnachMenu[i] = PageMenu;
            break;
        case 3:         // всего страниц Меню
              ZnachMenu[i] = maxStr;
            break;    
    }
    if (ZnachMenu[i]!=previousZnachMenu[i] || obnovitValueMenu[i]) {
                obnovitValueMenu[i]=true;
                prevZnachMenu[i]=previousZnachMenu[i];
                previousZnachMenu[i]=ZnachMenu[i];
              switch (i) {
                case 0:       // температура в салоне автомобиля
                    if(obnovitValueMenu[i]){
                        obnovitValueMenu[i]=false;
                        temperatureAvtoMenu();
                    }  
                    break;
                case 1:       // время
                    if(obnovitValueMenu[i]){
                        obnovitValueMenu[i]=false;
                        timeBoxMenu();
                    }
                    break;
                case 2:       // текущая страница Меню
                    if(obnovitValueMenu[i]){
                        obnovitValueMenu[i]=false;
                        nomerPageMenu();
                    }
                    break;
                case 3:       // всего страниц Меню
                    if(obnovitValueMenu[i]){
                        obnovitValueMenu[i]=false;
                        maxPageMenu();
                    }
                    break;    
              }             
      }          
  }
}

void ObnovlenieUn(){
      int un;
      int SravnenieUn;
      int ZnachUn=nUkazatel;

    SravnenieUn = ZnachUn - previousZnachUn;    // направление перемещения
  for(un=0; un< Menus[actualIndex].letArray; un++){    
      if(ZnachUn!=previousZnachUn || obnovitValueUn[un]) {
          if(nUkazatel> Menus[actualIndex].letArray -1) nUkazatel=0;
          if(nUkazatel<0) nUkazatel= Menus[actualIndex].letArray -1;
              ZnachUn=nUkazatel;
              obnovitValueUn[ZnachUn]=true;
              previousZnachUn=ZnachUn;
            switch (un) {
              case 0:       // 
                  if(obnovitValueUn[un]){
                      obnovitValueUn[un]=false;
                    if(SravnenieUn>0 && Menus[actualIndex].letArray ==6) rcZamena=5;
                    if(SravnenieUn>0 && Menus[actualIndex].letArray ==5) rcZamena=4;
                    if(SravnenieUn>0 && Menus[actualIndex].letArray ==4) rcZamena=3;
                    if(SravnenieUn>0 && Menus[actualIndex].letArray ==3) rcZamena=2;
                    if(SravnenieUn>0 && Menus[actualIndex].letArray ==2) rcZamena=1;
                    if(SravnenieUn<0) rcZamena=1;
                      RamkaCircleZamena();    // 88
                      circleUkazatel();       // 109
                  }  
                  break;
              case 1:       // 
                  if(obnovitValueUn[un]){
                      obnovitValueUn[un]=false;
                    if(SravnenieUn>0) rcZamena=0;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray >2) rcZamena=2;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray ==2) rcZamena=0; 
                      RamkaCircleZamena();  
                      circleUkazatel();     
                  }
                  break;
              case 2:       // 
                  if(obnovitValueUn[un]){
                      obnovitValueUn[un]=false;
                    if(SravnenieUn>0) rcZamena=1;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray >3) rcZamena=3;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray ==3) rcZamena=0;
                      RamkaCircleZamena(); 
                      circleUkazatel();
                  }
                  break;
              case 3:       // 
                  if(obnovitValueUn[un]){
                      obnovitValueUn[un]=false;
                    if(SravnenieUn>0) rcZamena=2;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray >4) rcZamena=4;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray ==4) rcZamena=0;
                      RamkaCircleZamena(); 
                      circleUkazatel();
                  }
                  break;
              case 4:       // 
                  if(obnovitValueUn[un]){
                      obnovitValueUn[un]=false;
                    if(SravnenieUn>0) rcZamena=3;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray >5) rcZamena=5;
                    if(SravnenieUn<0 && Menus[actualIndex].letArray ==5) rcZamena=0;
                      RamkaCircleZamena(); 
                      circleUkazatel();
                  }               
                  break;
              case 5:       // 
                  if(obnovitValueUn[un]){
                      obnovitValueUn[un]=false;
                    if(SravnenieUn>0) rcZamena=4;
                    if(SravnenieUn<0) rcZamena=0;
                      RamkaCircleZamena(); 
                      circleUkazatel();
                  }              
                  break;
            }            
    }          
  }   
}

void RamkaCircleZamena(){
  if(rcZamena==0){
    tft.fillRect(70, 62, 33, 20, colorUkazatelEraseMenu);  // 0
    tft.drawFastVLine(76, 86, -6, colorZamenaMenu);  // 12
    tft.drawFastVLine(77, 83, -6, colorZamenaMenu);
    tft.drawFastVLine(78, 80, -6, colorZamenaMenu);
    tft.drawFastVLine(79, 77, -6, colorZamenaMenu);
    tft.drawFastVLine(80, 74, -6, colorZamenaMenu);
    tft.drawFastVLine(81, 71, -5, colorZamenaMenu);  
    tft.drawFastVLine(82, 68, -5, colorZamenaMenu);
    tft.drawFastVLine(83, 66, -5, colorZamenaMenu);
    tft.drawFastVLine(84, 63, -5, colorZamenaMenu);  // 20
  }
  if(rcZamena==1){
    tft.fillRect(70-10, 62+35, 33+10, 20, colorUkazatelEraseMenu);  // 1
    tft.drawFastVLine(68, 124, -13, colorZamenaMenu);  // 4
    tft.drawFastVLine(69, 117, -11, colorZamenaMenu);
    tft.drawFastVLine(70, 111, -9, colorZamenaMenu);
    tft.drawFastVLine(71, 106, -8, colorZamenaMenu);  
    tft.drawFastVLine(72, 102, -8, colorZamenaMenu);  // 8
  }
  if(rcZamena==2){
    tft.fillRect(70-14, 62+70, 33+14, 20, colorUkazatelEraseMenu);  // 2
    tft.drawFastVLine(64, 143, 10, colorZamenaMenu);  // 0
    tft.drawFastVLine(65, 132, 21, colorZamenaMenu);     
    tft.drawFastVLine(66, 143, -19, colorZamenaMenu);  // 2 
  }
  if(rcZamena==3){
    tft.fillRect(70-14, 62+105, 33+14, 20, colorUkazatelEraseMenu);  // 3
    tft.drawFastVLine(64, 166, 10, colorZamenaMenu);  // 0
    tft.drawFastVLine(65, 166, 21, colorZamenaMenu);
    tft.drawFastVLine(66, 176, 19, colorZamenaMenu);  // 2
  }
  if(rcZamena==4){
    tft.fillRect(70-10, 62+140, 33+10, 20, colorUkazatelEraseMenu);  // 4
    tft.drawFastVLine(68, 195, 13, colorZamenaMenu);  // 4
    tft.drawFastVLine(69, 202, 11, colorZamenaMenu);
    tft.drawFastVLine(70, 208, 9, colorZamenaMenu);
    tft.drawFastVLine(71, 213, 8, colorZamenaMenu);  
    tft.drawFastVLine(72, 217, 8, colorZamenaMenu);  // 8
  }
  if(rcZamena==5){
    tft.fillRect(70, 62+175, 33, 20, colorUkazatelEraseMenu);  // 5
    tft.drawFastVLine(76, 233, 6, colorZamenaMenu);  // 12
    tft.drawFastVLine(77, 236, 6, colorZamenaMenu);
    tft.drawFastVLine(78, 239, 6, colorZamenaMenu);
    tft.drawFastVLine(79, 242, 6, colorZamenaMenu);
    tft.drawFastVLine(80, 245, 6, colorZamenaMenu);
    tft.drawFastVLine(81, 248, 5, colorZamenaMenu);  
    tft.drawFastVLine(82, 251, 5, colorZamenaMenu);
    tft.drawFastVLine(83, 253, 5, colorZamenaMenu);
    tft.drawFastVLine(84, 256, 5, colorZamenaMenu);  // 20    
  }  
}

void circleUkazatel(){
    int x=1, y, z;
  if(nUkazatel==0) z=0;
  if(nUkazatel==1) z=10;
  if(nUkazatel==2) z=14;
  if(nUkazatel==3) z=14;
  if(nUkazatel==4) z=10;
  if(nUkazatel==5) z=0;
  
    y=nUkazatel*35;

      tft.drawRoundRect(70-z, 62+y, 20, 20, 10, RED);
      tft.drawRoundRect(71-z, 63+y, 18, 18, 8, RED);
      tft.fillRoundRect(74-z, 66+y, 12, 12, 4, WHITE);
      tft.fillRect(89+x-z, 72+y, 13+z, 2, RED); 
}

void showTriangle(byte state){
  if(state == 0){       // вертикальное перемещение
    for(int n=0; n< Menus[actualIndex].letArray; n++){
      if(n == strelkaArray-1){
        tft.fillTriangle(368, 64+n*35, 383, 72+n*35, 368, 80+n*35, WHITE);  // белый треугольник
      }else{
        tft.drawTriangle(368, 64+n*35, 383, 72+n*35, 368, 80+n*35, RED);  // красный треугольник
        tft.drawTriangle(369, 65+n*35, 382, 72+n*35, 369, 79+n*35, RED);  // красный треугольник
      }
    }  
  }else if(state == 1){   // горизонтальное перемещение
        int s=strelkaArray-1;
        int t=prevParentStrelka-1;
    if(Menus[actualIndex].letArray > 1){    
      tft.fillTriangle(368, 64+s*35, 383, 72+s*35, 368, 80+s*35, WHITE);  // белый треугольник
          tft.fillRect(368, 64+t*35, 16, 18, BLACK);
      tft.drawTriangle(368, 64+t*35, 383, 72+t*35, 368, 80+t*35, RED);  // красный треугольник
      tft.drawTriangle(369, 65+t*35, 382, 72+t*35, 369, 79+t*35, RED);
    }else if(Menus[actualIndex].letArray == 1){
      tft.fillTriangle(368, 64+s*35, 383, 72+s*35, 368, 80+s*35, WHITE);  // белый треугольник 
    }
  }      
}

void clearTriangle(){
    tft.fillRect(368, 64, 16, 192, BLACK);
}
void ShowMenu(){
    RamkaPerimetr();
      redRamka();
      circleRamka();
    StartMenu();
      showTriangle(0);
      exitDoor();
      backStrelka();
      startPage();
      strelkaVKruge(); 
}
//************************************************************************************
void strelkaVKruge(){
  int x=432, y=110, r=12, s=1, st=1;
    tft.drawCircle(x, y, r, RED);         // круги
    tft.drawCircle(x, y, r-1, RED);
    tft.drawCircle(x, y+98, r, RED);
    tft.drawCircle(x, y+98, r-1, RED);

  for(int k=0; k<3; k++){
    if(k==0){ 
      tft.drawFastVLine(x+2-s, 126, 6, RED); tft.drawFastVLine(x+2-s, 193, -6, RED);    // линии
      tft.drawFastVLine(x+3+s, 126, 6, RED); tft.drawFastVLine(x+3+s, 193, -6, RED);
    }
    if(k==1){ 
      tft.drawFastVLine(x+3-s, 132, 11, RED); tft.drawFastVLine(x+3-s, 187, -11, RED);
      tft.drawFastVLine(x+4+s, 132, 11, RED); tft.drawFastVLine(x+4+s, 187, -11, RED);
    }
    if(k==2){ 
      tft.drawFastVLine(x+4-s, 143, 33, RED); 
      tft.drawFastVLine(x+5+s, 143, 33, RED);
    }    
  } 
      tft.fillTriangle(x-1, y-2-st, x-4, y+3-st, x+4, y+1-st, RED);           // стрелка Вверх
      tft.fillTriangle(x-1, y+98+2+st, x-4, y+98-3+st, x+4, y+98-1+st, RED);  // стрелка Вниз

      tft.drawPixel(x-2, y-1-st, RED);    // коррекция верхней стрелки
      tft.drawPixel(x+1, y-1-st, RED);
      tft.drawPixel(x-3, y-st, RED);
      tft.drawPixel(x+3, y-st, RED);
      tft.drawPixel(x-3, y+1-st, RED);
      tft.drawPixel(x-4, y+2-st, RED); 
}

void exitDoor(){
  int xTr=433, yTr=276;
  int x=424, y=242;
    tft.drawRect(x, y, 40, 60, colorExitMenu);        // дверь
    tft.drawRect(x+1, y+1, 38, 58, colorExitMenu);    // дверь
    tft.fillRect(x, y+9, 2, 19, BLACK);
    
    tft.drawRect(x-12, y+7, 40, 23, colorExitMenu);   // надпись
    tft.drawRect(x-11, y+8, 38, 21, colorExitMenu);   // надпись
    
    tft.drawRect(xTr-20, yTr+5, 21, 10, colorExitMenu);   // стрелка 
    tft.drawRect(xTr-19, yTr+6, 20, 8, colorExitMenu);    // стрелка  
    tft.drawTriangle(xTr, yTr+1, xTr, yTr+17, xTr+8, yTr+9, ColorLineMenu);      // красный треугольник
    tft.drawTriangle(xTr+1, yTr+3, xTr+1, yTr+15, xTr+7, yTr+9, ColorLineMenu);  // красный треугольник

    tft.fillRect(xTr, yTr+7, 2, 6, BLACK);
    tft.fillRect(x, y+41, 2, 6, BLACK);   
    
      tft.setTextColor(colorExitMenu);
    showmsgXY(x-7, y+23, 1, &FreeSans9pt7b, "exit");
}

void backStrelka(){
    int xTr=27, yTr=10;
  tft.drawRoundRect(xTr-11, yTr+7, 68, 28, 14, RED);
  tft.drawRoundRect(xTr-10, yTr+8, 66, 26, 12, RED);
  tft.drawFastHLine(xTr+1, yTr+9, 46, RED);
  
  tft.fillRect(xTr-13, yTr+4, 13, 36, BLACK);
  tft.fillRect(xTr, yTr+33, 25, 2, BLACK);
  tft.drawFastHLine(xTr+1, yTr+8, 45, BLACK);
  
  tft.drawTriangle(xTr, yTr, xTr, yTr+16, xTr-8, yTr+8, ColorLineMenu);
  tft.drawTriangle(xTr-1, yTr+2, xTr-1, yTr+14, xTr-7, yTr+8, ColorLineMenu);

  tft.fillRect(xTr-1, yTr+7, 2, 3, BLACK);
  
    tft.setTextColor(RED);
  showmsgXY(35, 36, 1, &FreeSans9pt7b, "back");
}

void nomerPageMenu(){
    tft.setTextColor(RED);
    tft.fillRect(51, 279, 11, 17, BLACK);
  showmsg2XY(50, 295, 1, &FreeSans12pt7b, PageMenu);    // int
    tft.setFont();
    tft.setTextSize(TextSize);
}

void maxPageMenu(){
      tft.setTextColor(RED);
      tft.fillRect(71, 279, 11, 17, BLACK);  
    showmsg2XY(70, 295, 1, &FreeSans12pt7b, maxStr); 
  if(maxStr == 1){
      tft.fillRect(51, 278, 11, 18, BLACK);
    showmsg2XY(50, 295, 1, &FreeSans12pt7b, prevMaxStr);
  }
    tft.setFont();
    tft.setTextSize(TextSize);
}

void startPage(){
  showmsgXY(50, 295, 1, &FreeSans12pt7b, "1/2");
}
//******************************************[ РАМКА ]****************************************************
void redRamka(){
    tft.drawFastHLine(90, 47, 309+dMenu, RED);
    tft.drawFastHLine(90, 48, 309+dMenu, RED);

    tft.drawFastHLine(90, 270, 309+dMenu, RED);
    tft.drawFastHLine(90, 271, 309+dMenu, RED);
}

void circleRamka(){
      int x=64, y=159;
      int h;
 for(h=0; h<=26; h++){
   if(h==0) {
     tft.drawFastVLine(64, 143, 33, ColorCircleMenu);
     tft.drawFastVLine(424+dMenu, 143, 33, ColorCircleMenu);
   }
   if(h==1) {
     tft.drawFastVLine(65, 132, 55, ColorCircleMenu);
     tft.drawFastVLine(423+dMenu, 132, 55, ColorCircleMenu);
   }
   if(h==2) {
     tft.drawFastVLine(66, 143, -19, ColorCircleMenu); tft.drawFastVLine(66, 176, 19, ColorCircleMenu);
     tft.drawFastVLine(422+dMenu, 143, -19, ColorCircleMenu); tft.drawFastVLine(422+dMenu, 176, 19, ColorCircleMenu);
   }
   if(h==3) {
     tft.drawFastVLine(67, 132, -15, ColorCircleMenu); tft.drawFastVLine(67, 187, 15, ColorCircleMenu);
     tft.drawFastVLine(421+dMenu, 132, -15, ColorCircleMenu); tft.drawFastVLine(421+dMenu, 187, 15, ColorCircleMenu);
   } 
   if(h==4) {
     tft.drawFastVLine(68, 124, -13, ColorCircleMenu); tft.drawFastVLine(68, 195, 13, ColorCircleMenu);
     tft.drawFastVLine(420+dMenu, 124, -13, ColorCircleMenu); tft.drawFastVLine(420+dMenu, 195, 13, ColorCircleMenu);
   }  
   if(h==5) {
     tft.drawFastVLine(69, 117, -11, ColorCircleMenu); tft.drawFastVLine(69, 202, 11, ColorCircleMenu);
     tft.drawFastVLine(419+dMenu, 117, -11, ColorCircleMenu); tft.drawFastVLine(419+dMenu, 202, 11, ColorCircleMenu);
   } 
   if(h==6) {
     tft.drawFastVLine(70, 111, -9, ColorCircleMenu); tft.drawFastVLine(70, 208, 9, ColorCircleMenu);
     tft.drawFastVLine(418+dMenu, 111, -9, ColorCircleMenu); tft.drawFastVLine(418+dMenu, 208, 9, ColorCircleMenu);
   }
   if(h==7) {
     tft.drawFastVLine(71, 106, -8, ColorCircleMenu); tft.drawFastVLine(71, 213, 8, ColorCircleMenu);
     tft.drawFastVLine(417+dMenu, 106, -8, ColorCircleMenu); tft.drawFastVLine(417+dMenu, 213, 8, ColorCircleMenu);
   }
   if(h==8) {
     tft.drawFastVLine(72, 102, -8, ColorCircleMenu); tft.drawFastVLine(72, 217, 8, ColorCircleMenu);
     tft.drawFastVLine(416+dMenu, 102, -8, ColorCircleMenu); tft.drawFastVLine(416+dMenu, 217, 8, ColorCircleMenu);
   }
   if(h==9) {
     tft.drawFastVLine(73, 98, -8, ColorCircleMenu); tft.drawFastVLine(73, 221, 8, ColorCircleMenu);
     tft.drawFastVLine(415+dMenu, 98, -8, ColorCircleMenu); tft.drawFastVLine(415+dMenu, 221, 8, ColorCircleMenu);
   }
   if(h==10) {
     tft.drawFastVLine(74, 94, -8, ColorCircleMenu); tft.drawFastVLine(74, 225, 8, ColorCircleMenu);
     tft.drawFastVLine(414+dMenu, 94, -8, ColorCircleMenu); tft.drawFastVLine(414+dMenu, 225, 8, ColorCircleMenu);
   }
   if(h==11) {
     tft.drawFastVLine(75, 90, -7, ColorCircleMenu); tft.drawFastVLine(75, 229, 7, ColorCircleMenu);
     tft.drawFastVLine(413+dMenu, 90, -7, ColorCircleMenu); tft.drawFastVLine(413+dMenu, 229, 7, ColorCircleMenu);
   }
   if(h==12) {
     tft.drawFastVLine(76, 86, -6, ColorCircleMenu); tft.drawFastVLine(76, 233, 6, ColorCircleMenu);
     tft.drawFastVLine(412+dMenu, 86, -6, ColorCircleMenu); tft.drawFastVLine(412+dMenu, 233, 6, ColorCircleMenu);
   }
   if(h==13) {
     tft.drawFastVLine(77, 83, -6, ColorCircleMenu); tft.drawFastVLine(77, 236, 6, ColorCircleMenu);
     tft.drawFastVLine(411+dMenu, 83, -6, ColorCircleMenu); tft.drawFastVLine(411+dMenu, 236, 6, ColorCircleMenu);
   }
   if(h==14) {
     tft.drawFastVLine(78, 80, -6, ColorCircleMenu); tft.drawFastVLine(78, 239, 6, ColorCircleMenu);
     tft.drawFastVLine(410+dMenu, 80, -6, ColorCircleMenu); tft.drawFastVLine(410+dMenu, 239, 6, ColorCircleMenu);
   }
   if(h==15) {
     tft.drawFastVLine(79, 77, -6, ColorCircleMenu); tft.drawFastVLine(79, 242, 6, ColorCircleMenu);
     tft.drawFastVLine(409+dMenu, 77, -6, ColorCircleMenu); tft.drawFastVLine(409+dMenu, 242, 6, ColorCircleMenu);
   }
   if(h==16) {
     tft.drawFastVLine(80, 74, -6, ColorCircleMenu); tft.drawFastVLine(80, 245, 6, ColorCircleMenu);
     tft.drawFastVLine(408+dMenu, 74, -6, ColorCircleMenu); tft.drawFastVLine(408+dMenu, 245, 6, ColorCircleMenu);
   }
   if(h==17) {
     tft.drawFastVLine(81, 71, -5, ColorCircleMenu); tft.drawFastVLine(81, 248, 5, ColorCircleMenu);
     tft.drawFastVLine(407+dMenu, 71, -5, ColorCircleMenu); tft.drawFastVLine(407+dMenu, 248, 5, ColorCircleMenu);
   }
   if(h==18) {
     tft.drawFastVLine(82, 68, -5, ColorCircleMenu); tft.drawFastVLine(82, 251, 5, ColorCircleMenu);
     tft.drawFastVLine(406+dMenu, 68, -5, ColorCircleMenu); tft.drawFastVLine(406+dMenu, 251, 5, ColorCircleMenu);
   }
   if(h==19) {
     tft.drawFastVLine(83, 66, -5, ColorCircleMenu); tft.drawFastVLine(83, 253, 5, ColorCircleMenu);
     tft.drawFastVLine(405+dMenu, 66, -5, ColorCircleMenu); tft.drawFastVLine(405+dMenu, 253, 5, ColorCircleMenu);
   }
   if(h==20) {
     tft.drawFastVLine(84, 63, -5, ColorCircleMenu); tft.drawFastVLine(84, 256, 5, ColorCircleMenu);
     tft.drawFastVLine(404+dMenu, 63, -5, ColorCircleMenu); tft.drawFastVLine(404+dMenu, 256, 5, ColorCircleMenu);
   }
   if(h==21) {
     tft.drawFastVLine(85, 61, -5, ColorCircleMenu); tft.drawFastVLine(85, 258, 5, ColorCircleMenu);
     tft.drawFastVLine(403+dMenu, 61, -5, ColorCircleMenu); tft.drawFastVLine(403+dMenu, 258, 5, ColorCircleMenu);
   }
   if(h==22) {
     tft.drawFastVLine(86, 58, -4, ColorCircleMenu); tft.drawFastVLine(86, 261, 4, ColorCircleMenu);
     tft.drawFastVLine(402+dMenu, 58, -4, ColorCircleMenu); tft.drawFastVLine(402+dMenu, 261, 4, ColorCircleMenu);
   }
   if(h==23) {
     tft.drawFastVLine(87, 56, -4, ColorCircleMenu); tft.drawFastVLine(87, 263, 4, ColorCircleMenu);
     tft.drawFastVLine(401+dMenu, 56, -4, ColorCircleMenu); tft.drawFastVLine(401+dMenu, 263, 4, ColorCircleMenu);
   }
   if(h==24) {
     tft.drawFastVLine(88, 54, -4, ColorCircleMenu); tft.drawFastVLine(88, 265, 4, ColorCircleMenu);
     tft.drawFastVLine(400+dMenu, 54, -4, ColorCircleMenu); tft.drawFastVLine(400+dMenu, 265, 4, ColorCircleMenu);
   }
   if(h==25) {
     tft.drawFastVLine(89, 52, -4, ColorCircleMenu); tft.drawFastVLine(89, 267, 4, ColorCircleMenu);
     tft.drawFastVLine(399+dMenu, 52, -4, ColorCircleMenu); tft.drawFastVLine(399+dMenu, 267, 4, ColorCircleMenu);
   }
   if(h==26) {
     tft.drawFastVLine(90, 50, -3, ColorCircleMenu); tft.drawFastVLine(90, 269, 3, ColorCircleMenu);
     tft.drawFastVLine(398+dMenu, 50, -3, ColorCircleMenu); tft.drawFastVLine(398+dMenu, 269, 3, ColorCircleMenu);
   }
 }
}

void RamkaPerimetr(){    // рисование линии по-горизонтали
// начало координат из левой верхней точки (гориз, верт, длина линии)

  tft.drawFastHLine(0, 0, 369, DARKGREY);    // верхняя линия
  tft.drawFastHLine(31, 319, 439, DARKGREY); // нижняя линия

// рисование линии по-вертикали   
  for(int y=0; y<319; y++){             // левая линия
      int x;
    if(y<20)x=0;                        // 0                              
    if(y>=20 && y<40)x=(y-20)/2;        // 10
    if(y>=40 && y<80)x=10+(y-40)/2.5;   // 26
    if(y>=80 && y<140)x=26+(y-80)/4;    // 41
    if(y>=140 && y<185)x=41+(y-140)/7;  // 47
    if(y>=185 && y<215)x=48;            // 48
    if(y>=215 && y<260)x=48-(y-215)/9;  // 43
    if(y>=260 && y<319)x=43-(y-260)/5;  // 31
      tft.drawPixel(x, y, DARKGREY);      // (гориз, верт) x, y
  }
    
  for(int y=0; y<320; y++){               // правая линия
      int x;
    if(y<32)x=370+y;                      // 402    
    if(y>=32 && y<68)x=402+(y-32)/1.3;    // 429
    if(y>=68 && y<103)x=429+(y-68)/1.8;   // 448
    if(y>=103 && y<135)x=448+(y-103)/2.2; // 462
    if(y>=135 && y<174)x=462+(y-135)/3;   // 475
    if(y>=174 && y<210)x=475+(y-174)/9;   // 479
    if(y>=210 && y<260)x=479;             // 479
    if(y>=260 && y<319)x=479-(y-260)/6;   // 470
      tft.drawPixel(x, y, DARKGREY);           // (гориз, верт) x, y
  }
} 
//*************************************[ БК ]********************************************************            
void Obnovlenie(){
  for(byte i=0; i<=15; i++){
    switch (i) {      // вывод на экран в первой строке выбранного параметра
        case 0:       // температура двигателя
              Znach[i] = Tdvig;
            break;
        case 1:       // напряжение АКБ
              Znach[i] = VolAKB;
            break;
        case 2:         // суточный пробег
              Znach[i] = ProbegSut;
            break;
        case 3:         // уровень газа в баке
              Znach[i] = GasL;
            break;
        case 4:         // уровень бензина в баке
              Znach[i] = BenzinL;
            break;
        case 5:         // номер включенной передачи
              Znach[i] = PeredachaN;
            break;
        case 6:         // Время
              Znach[i] = t.min;
            break;
        case 7:       // иконка Температуры двигателя
              Znach[i] = indexColorT;
            break;
        case 8:       // иконка Бензина в баке
              Znach[i] = indexColorB;
            break;
        case 9:         // иконка включения Круиза 
              Znach[i] = indexColorKk;
            break;
        case 10:         // скорость подхвата Круиза
              Znach[i] = SpeedKruise; 
            break;
        case 11:         // знак температуры двигателя
              Znach[i] = ZnakTdvig;
            break;
        case 12:         // иконка Вентиллятора охлаждения
              Znach[i] = flagKulerOn;
            break;
        case 13:         // иконка варианта света
              Znach[i] = indexColorSvet;
            break;
        case 14:         // иконка спущенной Шины
              Znach[i] = flagChinaOn;
            break;
        case 15:         // иконка Гололеда (Снежинка)
              Znach[i] = flagSnowOn; 

            break;     
    }
    if (Znach[i]!=previousZnach[i] || obnovitValue[i]) {
                obnovitValue[i]=true;
                prevZnach[i]=previousZnach[i];
                previousZnach[i]=Znach[i];
              switch (i) {
                case 0:       // температура двигателя
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                        temperatureDigit();
                    }  
                    break;
                case 1:       // напряжение АКБ
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                        volumeAKB();
                    }
                    break;
                case 2:       // суточный пробег
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                        probegDigit();
                    }
                    break;
                case 3:       // уровень газа в баке
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                        gasDigit();
                    }
                    break;
                case 4:       // уровень бензина в баке
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                        benzinDigit();
                    }                
                    break;
                case 5:       // номер включенной передачи (-, 1, 2, 3, 4, 5, N, R, P)
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                        peredachaDigit();
                    }                
                    break;
                case 6:       // время
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                        timeBox();
                    }                
                    break;   
                case 7:       // иконка Температуры двигателя
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(indexColorT ==0)colorTemperature=DARKGREY;
                      if(indexColorT ==1)colorTemperature=BLUE;
                      if(indexColorT ==2)colorTemperature=WHITE;  
                      if(indexColorT ==3)colorTemperature=RED;
                        showIconTemperature();
                    }   
                    break;
                case 8:       // иконка Бензина в баке
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(indexColorB ==0)colorFuel=DARKGREY;
                      if(indexColorB ==1)colorFuel=RED;
                      if(indexColorB ==2)colorFuel=WHITE;
                      if(indexColorB ==3)colorFuel=GREEN; 
                        showIconFuel();
                    }
                    break;
                case 9:       // иконка включения Круиза 
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(indexColorKk ==0){
                        colorKruise=DARKGREY; 
                        colorTextSpeed=BLACK;
                        tft.fillRect(41, 62, 37, 17, BLACK);
                      }
                      if(indexColorKk ==1){
                        colorKruise=RED; 
                        colorTextSpeed=BLACK;
                        tft.fillRect(41, 62, 37, 17, BLACK);
                      }
                      if(indexColorKk ==2){
                          colorKruise=DARKGREEN; 
                          colorTextSpeed=DARKGREEN;
                        obnovitSpeedKr[0] = true; obnovitSpeedKr[1] = true; obnovitSpeedKr[2] = true;
                          showSpeedKruise();
                      }
                        showIconKruise();
                        showTextSpeed();            // + км/ч
                    }
                    break;
                case 10:       // скорость подхвата Круиза  
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(Podhvat==true){
                          colorTextSpeed=DARKGREEN;
                          showSpeedKruise();
                      }
                    }
                    break;
                case 11:       // знак температуры двигателя
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(Tdvig>=0 && Tdvig <100)tft.fillRect(64, 229, 17, 25, BLACK);
                      if(ZnakTdvig == false){
                          tft.fillRect(64, 244, 14, 3, WHITE);      // -
                      } 
                    }                
                    break;
                case 12:       // иконка Вентиллятора охлаждения
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(flagKulerOn==true){
                          colorKuler=BLUE;
                      }else{
                          colorKuler=DARKGREY;
                      }
                        showIconKuler();  
                    }                
                    break;
                case 13:       // иконка варианта света
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(indexColorSvet==0){           // все включено
                          colorFara=DARKGREY;
                          showIconFara();
                      }
                      if(indexColorSvet==1){           // ДХО включены
                          colorDXO=WHITE;
                          showIconDXO();
                      }
                      if(indexColorSvet==2){           // Габариты включены
                          colorGabarity=GREEN;
                          showIconGabarity();
                      }
                      if(indexColorSvet==3){           // Ближний Свет включен
                          colorFara=GREEN;
                          showIconFara();
                      }
                    }                
                    break;  
                case 14:       // иконка спущенной Шины
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(flagChinaOn==true){
                          colorChina=RED;                     // зажигается красная иконка Шина
                      }else{
                          colorChina=DARKGREY;
                      }
                          showIconChina();
                    } 
                    break;
                case 15:       // иконка Гололеда (Снежинка)
                    if(obnovitValue[i]){
                        obnovitValue[i]=false;
                      if(flagSnowOn==true){
                          colorSnow=WHITE;
                      }else{
                          colorSnow=DARKGREY;
                      }
                          showIconSnow();
                    }            
                    break;
              }             
      }          
  }
}
// ------------------------------------------------------------------------------------------------------
void ObnovlenieT(){       // обновление шкалы уровня температуры двигателя
        int st;
        int SravnenieT;
        int ZnachT=ScaleT;
    for(st=0; st<=8; st++){    
        if (ZnachT!=previousZnachT || obnovitValueT[st]) {
          if(ZnachT > previousZnachT){
              obnovitValueT[ZnachT]=true;
          }else{
              obnovitValueT[previousZnachT]=true;
          }
            SravnenieT = ZnachT - previousZnachT;
          if(abs(SravnenieT)>1){
              for(int k=0; k<=8; k++){
                  obnovitValueT[k]=true;
              }
          }
            previousZnachT=ZnachT;
              switch (st) {
                case 0:       // 50
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig < 50){
                          colorScaleT=BLACK;
                      }else{
                          colorScaleT=BLUE;
                      }
                        tft.fillRect(x1Scale+2, yScale+2, 20, 8, colorScaleT);
                    }  
                    break;
                case 1:       // 60
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 59){
                          colorScaleT=WHITE;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-2, yScale-13, 20, 8, colorScaleT);
                    }
                    break;
                case 2:       // 70
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 69){
                          colorScaleT=WHITE;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-7, yScale-28, 20, 8, colorScaleT);
                    }
                    break;
                case 3:       // 80
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 79){
                          colorScaleT=WHITE;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-13, yScale-43, 20, 8, colorScaleT); 
                    }
                    break;
                case 4:       // 90
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 89){
                          colorScaleT=WHITE;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-21, yScale-58, 20, 8, colorScaleT);
                    }               
                    break;
                case 5:       // 100
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 99){
                          colorScaleT=WHITE;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-30, yScale-73, 20, 8, colorScaleT);
                    }              
                    break;
                case 6:       // 110
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 109){
                          colorScaleT=RED;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-42, yScale-88, 20, 8, colorScaleT);
                    }               
                    break;   
                case 7:       // 120
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 119){
                          colorScaleT=RED;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-56, yScale-103, 20, 8, colorScaleT); 
                    }  
                    break;
                case 8:       // 130
                    if(obnovitValueT[st]){
                        obnovitValueT[st]=false;
                      if(Tdvig > 129){
                          colorScaleT=RED;      
                      }else{
                          colorScaleT=BLACK;
                      }
                        tft.fillRect(x1Scale-74, yScale-118, 20, 8, colorScaleT); 
                    }
                    break;                  
              }             
      }          
  }
}
// ------------------------------------------------------------------------------------------------------
void ObnovlenieB(){       // обновление шкалы уровня бензина в баке
        int sb;
        int SravnenieB;
        int ZnachB=ScaleB;
    for(sb=0; sb<=8; sb++){    
        if (ZnachB!=previousZnachB || obnovitValueB[sb]) {
          if(ZnachB > previousZnachB){
              obnovitValueB[ZnachB]=true;
          }else{
              obnovitValueB[previousZnachB]=true;
          }
            SravnenieB = ZnachB - previousZnachB;
          if(abs(SravnenieB)>1){
              for(int n=0; n<=8; n++){
                  obnovitValueB[n]=true;
              }
          }
            previousZnachB=ZnachB;
              switch (sb) {
                case 0:       // 10
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL < 10){
                          colorScaleB=BLACK;
                      }else{
                          colorScaleB=RED;
                      }
                        tft.fillRect(x2Scale+2, yScale+2, 20, 8, colorScaleB);
                    }  
                    break;
                case 1:       // 15
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 14){
                          colorScaleB=WHITE;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+6, yScale-13, 20, 8, colorScaleB);
                    }
                    break;
                case 2:       // 20
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 19){
                          colorScaleB=WHITE;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+11, yScale-28, 20, 8, colorScaleB);
                    }
                    break;
                case 3:       // 25
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 24){
                          colorScaleB=WHITE;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+17, yScale-43, 20, 8, colorScaleB); 
                    }
                    break;
                case 4:       // 30
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 29){
                          colorScaleB=WHITE;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+25, yScale-58, 20, 8, colorScaleB);
                    }               
                    break;
                case 5:       // 35
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 34){
                          colorScaleB=WHITE;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+34, yScale-73, 20, 8, colorScaleB);
                    }              
                    break;
                case 6:       // 40
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 39){
                          colorScaleB=WHITE;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+46, yScale-88, 20, 8, colorScaleB);
                    }               
                    break;   
                case 7:       // 45
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 44){
                          colorScaleB=WHITE;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+60, yScale-103, 20, 8, colorScaleB); 
                    }  
                    break;
                case 8:       // 50
                    if(obnovitValueB[sb]){
                        obnovitValueB[sb]=false;
                      if(BenzinL > 49){
                          colorScaleB=GREEN;      
                      }else{
                          colorScaleB=BLACK;
                      }
                        tft.fillRect(x2Scale+78, yScale-118, 20, 8, colorScaleB); 
                    }
                    break;                  
              }             
      }          
  }
}
// ---------------------------------------------------------------------------------------------------------------
void BKreadData(){

    if(ProbegSut>=10000) ProbegSut=0;
  if(Init){
    Tdvig = ECT;
    VolAKB = VoltBS * 10;
  }else{
    Tdvig = map(analogRead(Temper_Dvig_Pin), 0, 950, -40, 130);
    VoltAKB = analogRead(Voltage_Pin)/60.0;
      VolAKB = VoltAKB * 10;
  }
      Speed = map(analogRead(Speed_KK_Pin), 0, 950, 0, 200);
      GasL = map(analogRead(Gaz_Pin), 0, 950, 0, 32);
      BenzinL = map(analogRead(Benzin_Pin), 0, 950, 0, 50);

      ScaleT = Tdvig/10 - 5;
      ScaleB = BenzinL/5 - 2;
      
    if(Tdvig < 60) indexColorT = 1;                 // Blue
    if(Tdvig > 59 && Tdvig < 110) indexColorT = 2;  // White
    if(Tdvig > 109) indexColorT = 3;                // Red

    if(BenzinL < 15) indexColorB = 1;                   // Red
    if(BenzinL > 14 && BenzinL < 50) indexColorB = 2;   // White
    if(BenzinL > 49) indexColorB = 3;                   // Green   
}
//****************************************************************************************************************

int readKey() {             // функция определения нажатой кнопки
  byte KeyNum=0;            // Читаем аналоговый вход, если значение > 1000 – значит не была нажата ни одна клавиша.

  int KeyValue=analogRead(Peredacha_Pin);
  if (KeyValue <= 1000) {
    for (int i=1; i<=5; i++) {
      if (KeyValue < Button[i-1]+20 && KeyValue > Button[i-1]-20) {
        KeyNum=i;           // сверяем значение на входе и определяем нажатую кнопку
      };
    };
  };
  return KeyNum;            // Возвращаем код нажатой кнопки
}
//****************************************************************************************************************
void SetDisplay(){
    FramePerimeter();     // кривая рамка по периметру экрана + 6 прямых полос в центре   // 415
    DugaMax();            // левая и правая нижние дуги в центре
    DugaMin();            // левая и правая верхние дуги в центре
      iconAuto();         // иконка автомобиля                      // 286
      iconStation();      // иконка точки отсчета                   // 309
      iconPoints();       // иконка точек прохождения               // 317
      iconAKB();          // иконка АКБ                             // 324
      drawScale();        // левая и правая загнутые шкалы температуры и бензина      // 145
      letterBox();        // km, °, С, H, E, F, L, L, точка АКБ и буква (v), двоеточие времени (:)    // 337
      letterStroka();     // надписи в строке пробега (KM, L, L/100)
}
// ---------------------------------------------------------------------------------------------------------
void probegDigit(){
    byte ProbSut[4], prevProbSut[4];
  if(ScreenBKvariant==0){ 
  
        prevProbSut[0]= prevZnach[2] /1000;
        prevProbSut[1]= prevZnach[2] %1000/100;
        prevProbSut[2]= prevZnach[2] %100/10;
        prevProbSut[3]= prevZnach[2] %10;

        ProbSut[0]= Znach[2] /1000;
        ProbSut[1]= Znach[2] %1000/100;
        ProbSut[2]= Znach[2] %100/10;
        ProbSut[3]= Znach[2] %10;

      for(byte p=0; p<4; p++){
        if (ProbSut[p]!=prevProbSut[p] || obnovitProbSut[p]) {
                obnovitProbSut[p]=true;
            switch (p) {
                case 0:      
                    if(obnovitProbSut[p]){                // 1000
                        obnovitProbSut[p]=false;
                          tft.setTextColor(colorAuto);
                          tft.fillRect(263, 84, 17, 25, BLACK);
                        if(Znach[2] >999)showmsg1XY(262, 108, 1, &FreeSans18pt7b, ProbSut[p]);   // byte
                    }  
                    break;
                case 1:       
                    if(obnovitProbSut[p]){                // 100
                        obnovitProbSut[p]=false;
                          tft.setTextColor(colorAuto);
                          tft.fillRect(283, 84, 17, 25, BLACK);
                        if(Znach[2] >99)showmsg1XY(282, 108, 1, &FreeSans18pt7b, ProbSut[p]);
                    }
                    break;
                case 2:      
                    if(obnovitProbSut[p]){                // 10
                        obnovitProbSut[p]=false;
                          tft.setTextColor(colorAuto);
                          tft.fillRect(303, 84, 17, 25, BLACK);
                        if(Znach[2] >9)showmsg1XY(302, 108, 1, &FreeSans18pt7b, ProbSut[p]);
                    }
                    break;
                case 3:      
                    if(obnovitProbSut[p]){                // 1
                        obnovitProbSut[p]=false;
                          tft.setTextColor(colorAuto);
                          tft.fillRect(323, 84, 17, 25, BLACK);
                        showmsg1XY(322, 108, 1, &FreeSans18pt7b, ProbSut[p]);
                    }
                    break;
            }
        }
      }
  }
}
void litrDigit(){
    int x=262, y=84;
  if(ScreenBKvariant==1){
    tft.setTextColor(colorAuto);
      showmsgXY(262, 108, 1, &FreeSans18pt7b, "9");
      showmsgXY(282, 108, 1, &FreeSans18pt7b, "9");
      showmsgXY(302, 108, 1, &FreeSans18pt7b, "9");
    tft.fillRect(322, 106, 3, 3, colorAuto);
      showmsgXY(326, 108, 1, &FreeSans18pt7b, "9");
  }  
}
void litrNaStoDigit(){
    int x=262, y=84;
  if(ScreenBKvariant==2){
    tft.setTextColor(colorAuto);
      showmsgXY(262, 108, 1, &FreeSans18pt7b, "9");
      showmsgXY(282, 108, 1, &FreeSans18pt7b, "9");
    tft.fillRect(303, 106, 3, 3, colorAuto);
      showmsgXY(307, 108, 1, &FreeSans18pt7b, "9");
  }   
}
void ostatokDigit(){
    int x=282, y=84;
  if(ScreenBKvariant==3 || ScreenBKvariant==4){
    tft.setTextColor(colorAuto);
      showmsgXY(282, 108, 1, &FreeSans18pt7b, "9");
      showmsgXY(302, 108, 1, &FreeSans18pt7b, "9");
      showmsgXY(322, 108, 1, &FreeSans18pt7b, "9");
  }    
}

void temperatureDigit(){
    byte TemperDvig[3], prevTemperDvig[3];             // 123
      
    tft.setTextColor(WHITE);
  if(Tdvig >= 0){       
      ZnakTdvig= true;           // +
  }else if(Tdvig < 0){        
      ZnakTdvig= false;          // -
  }
  
        prevTemperDvig[0]= prevZnach[0] /100;           // 1
        prevTemperDvig[1]= abs(prevZnach[0]) %100/10;   // 2
        prevTemperDvig[2]= abs(prevZnach[0]) %10;       // 3

        TemperDvig[0]= Znach[0] /100;
        TemperDvig[1]= abs(Znach[0]) %100/10;
        TemperDvig[2]= abs(Znach[0]) %10;

      for(byte td=0; td<3; td++){
        if (TemperDvig[td]!=prevTemperDvig[td] || obnovitTemperDvig[td]) {
                obnovitTemperDvig[td]=true;
            switch (td) {
                case 0:      
                    if(obnovitTemperDvig[td]){                // 100
                        obnovitTemperDvig[td]=false;
                          tft.fillRect(64, 229, 17, 25, BLACK);
                        if(Znach[0] >99)showmsg1XY(63, 253, 1, &FreeSans18pt7b, TemperDvig[td]);   // byte
                    }   
                    break;
                case 1:       
                    if(obnovitTemperDvig[td]){                // 10
                        obnovitTemperDvig[td]=false;
                          tft.fillRect(83, 229, 17, 25, BLACK);
                        if(abs(Znach[0]) >9)showmsg1XY(82, 253, 1, &FreeSans18pt7b, TemperDvig[td]);
                    }
                    break;
                case 2:      
                    if(obnovitTemperDvig[td]){                // 1
                        obnovitTemperDvig[td]=false;
                          tft.fillRect(102+1, 229, 17, 25, BLACK);
                        showmsg1XY(101+1, 253, 1, &FreeSans18pt7b, TemperDvig[td]);
                                             
                    }
                    break;
            }
        }
      }    
}
void benzinDigit(){
  byte FuelB[2], prevFuelB[2];              // 12
    tft.setTextColor(WHITE);
      
        prevFuelB[0]= prevZnach[4] /10;     // 1
        prevFuelB[1]= prevZnach[4] %10;     // 2

        FuelB[0]= Znach[4] /10;
        FuelB[1]= Znach[4] %10;

      for(byte fb=0; fb<2; fb++){
        if (FuelB[fb]!=prevFuelB[fb] || obnovitFuelB[fb]) {
                obnovitFuelB[fb]=true;
            switch (fb) {
                case 0:      
                    if(obnovitFuelB[fb]){                // 10
                        obnovitFuelB[fb]=false;
                          tft.fillRect(396, 229, 17, 25, BLACK);
                        if(Znach[4] >9)showmsg1XY(395, 253, 1, &FreeSans18pt7b, FuelB[fb]);   //
                    }  
                    break;
                case 1:       
                    if(obnovitFuelB[fb]){                // 1
                        obnovitFuelB[fb]=false;
                          tft.fillRect(415+1, 229, 17, 25, BLACK);
                        showmsg1XY(414+1, 253, 1, &FreeSans18pt7b, FuelB[fb]);
                    }
                    break;
            }
        }
      }   
}
void gasDigit(){
  byte FuelG[2], prevFuelG[2];              // 12
    tft.setTextColor(CYAN);
      
        prevFuelG[0]= prevZnach[3] /10;     // 1
        prevFuelG[1]= prevZnach[3] %10;     // 2

        FuelG[0]= Znach[3] /10;
        FuelG[1]= Znach[3] %10;

      for(byte fg=0; fg<2; fg++){
        if (FuelG[fg]!=prevFuelG[fg] || obnovitFuelG[fg]) {
                obnovitFuelG[fg]=true;
            switch (fg) {
                case 0:      
                    if(obnovitFuelG[fg]){                // 10
                        obnovitFuelG[fg]=false;
                          tft.fillRect(407, 140, 11, 17, BLACK);
                        if(Znach[3] >9)showmsg1XY(406, 156, 1, &FreeSans12pt7b, FuelG[fg]);   //
                    }  
                    break;
                case 1:       
                    if(obnovitFuelG[fg]){                // 1
                        obnovitFuelG[fg]=false;
                          tft.fillRect(420+1, 140, 11, 17, BLACK);
                        showmsg1XY(419+1, 156, 1, &FreeSans12pt7b, FuelG[fg]);
                    }
                    break;
            }
        }
      } 
}
void peredachaDigit(){
    tft.fillRect(241, 233, 39, 64, BLACK);
//  if(PeredachaN==0) tft.drawBitmap(241,233,CharNo,39,64, CYAN);   // нажато сцепление (--)
//  if(PeredachaN==1) tft.drawBitmap(241,233,Char1,39,64, CYAN);    // включена 1 передача
//  if(PeredachaN==2) tft.drawBitmap(241,233,Char2,39,64, CYAN);    // включена 2 передача
//  if(PeredachaN==3) tft.drawBitmap(241,233,Char3,39,64, CYAN);    // включена 3 передача
//  if(PeredachaN==4) tft.drawBitmap(241,233,Char4,39,64, CYAN);    // включена 4 передача
//  if(PeredachaN==5) tft.drawBitmap(241,233,Char5,39,64, CYAN);    // включена 5 передача
//  if(PeredachaN==6) tft.drawBitmap(241,233,CharN,39,64, CYAN);    // нейтраль N (нет включенной передачи)
//  if(PeredachaN==7) tft.drawBitmap(241,233,CharR,39,64, CYAN);    // включена R задняя передача
//  if(PeredachaN==8) tft.drawBitmap(241,233,CharP,39,64, CYAN);    // поднят ручник (парковка)
}
void volumeAKB(){ 
  byte VoltAKB[3], prevVoltAKB[3];                  // 123
      tft.setTextColor(colorAKB);

        prevVoltAKB[0]= prevZnach[1] /100;         // 1
        prevVoltAKB[1]= prevZnach[1] %100/10;      // 2
        prevVoltAKB[2]= prevZnach[1] %10;          // 3

        VoltAKB[0]= Znach[1] /100;
        VoltAKB[1]= Znach[1] %100/10;
        VoltAKB[2]= Znach[1] %10;
  
      for(byte v=0; v<3; v++){
        if (VoltAKB[v]!=prevVoltAKB[v] || obnovitVoltAKB[v]) {
                obnovitVoltAKB[v]=true;
            switch (v) {
                case 0:      
                    if(obnovitVoltAKB[v]){                // 100
                        obnovitVoltAKB[v]=false;
                          tft.fillRect(57, 140, 11, 17, BLACK);
                        if(VolAKB >99)showmsg1XY(56, 156, 1, &FreeSans12pt7b, VoltAKB[v]);   //
                    }  
                    break;
                case 1:       
                    if(obnovitVoltAKB[v]){                // 10
                        obnovitVoltAKB[v]=false;
                          tft.fillRect(70, 140, 11, 17, BLACK);
                        if(VolAKB >9)showmsg1XY(69, 156, 1, &FreeSans12pt7b, VoltAKB[v]);
                    }
                    break;
                case 2:       
                    if(obnovitVoltAKB[v]){                // 1
                        obnovitVoltAKB[v]=false;
                          tft.fillRect(89, 140, 11, 17, BLACK);
                        showmsg1XY(88, 156, 1, &FreeSans12pt7b, VoltAKB[v]);
                    }
                    break;
            }  
        }
      }
}
void timeBox(){
      int x=188, y=208;
      tft.setTextColor(colorTime);

    if(t.min!=minLast){
        prevTime[0]= hourLast /10;
        prevTime[1]= hourLast %10;
        prevTime[2]= minLast /10;
        prevTime[3]= minLast %10;

        dataTime[0]= t.hour /10;
        dataTime[1]= t.hour %10;
        dataTime[2]= t.min /10;
        dataTime[3]= t.min %10;
        
          hourLast = t.hour;
          minLast = t.min;  
    }
    
      for(byte tm=0; tm<4; tm++){
        if (dataTime[tm]!=prevTime[tm] || obnovitTime[tm]) {
                obnovitTime[tm]=true;
            switch (tm) {              
                case 0:      
                    if(obnovitTime[tm]){                // 10
                        obnovitTime[tm]=false;
                          tft.fillRect(x+2-1, y-48, 28, 46, BLACK);
                        if(hourLast > 9)showmsg1XY(x-1, y, 1, &FreeSevenSegNumFont, dataTime[tm]);          // минуты десятки
                    }
                    break;
                case 1:      
                    if(obnovitTime[tm]){                // 1
                        obnovitTime[tm]=false;
                          tft.fillRect(x+33, y-48, 28, 46, BLACK);
                        showmsg1XY(x+31, y, 1, &FreeSevenSegNumFont, dataTime[tm]);          // минуты единицы
                    }
                    break;
                case 2:      
                    if(obnovitTime[tm]){                // 10
                        obnovitTime[tm]=false;
                          tft.fillRect(x+84, y-48, 28, 46, BLACK);
                        showmsg1XY(x+82, y, 1, &FreeSevenSegNumFont, dataTime[tm]);   // часы десятки
                    }  
                    break;
                case 3:       
                    if(obnovitTime[tm]){                // 1
                        obnovitTime[tm]=false;
                          tft.fillRect(x+115+1, y-48, 28, 46, BLACK);
                        showmsg1XY(x+113+1, y, 1, &FreeSevenSegNumFont, dataTime[tm]);             // часы единицы  
                    }
                    break;
            }
        }
      }    
}

void showIconTemperature(){
//  tft.drawBitmap(70,268,IconTemperature,44,44, colorTemperature);
}
void showIconFuel(){
//  tft.drawBitmap(400,268,IconFuel,44,44, colorFuel);  
}
void showIconKruise(){
//  tft.drawBitmap(20,7,IconKruise,60,60, colorKruise);  
}
void showIconKuler(){
//  tft.drawBitmap(98,12,IconKuler,60,60, colorKuler);  
}
void showIconDXO(){
    tft.setTextColor(colorDXO);
    tft.fillRect(171, 12, 74, 60, BLACK);
  showmsgXY(170, 54, 1, &FreeSans18pt7b, "DXO");   
}
void showIconGabarity(){
    tft.fillRect(171, 12, 74, 60, BLACK);
//  tft.drawBitmap(177,12,IconGabarity,60,60, colorGabarity);  
}
void showIconFara(){
    tft.fillRect(171, 12, 74, 60, BLACK);
//  tft.drawBitmap(178,12,IconFara,60,60, colorFara);  
}
void showIconChina(){
//  tft.drawBitmap(258,12,IconChina,60,60, colorChina);  
}
void showIconSnow(){
//  tft.drawBitmap(328,12,IconSnow,60,60, colorSnow);  
}
void showSpeedKruise(){
  byte SpeedKr[3], prevSpeedKr[3];                 // 123
      tft.setTextColor(colorTextSpeed);

        prevSpeedKr[0]= prevZnach[10] /100;         // 1
        prevSpeedKr[1]= prevZnach[10] %100/10;      // 2
        prevSpeedKr[2]= prevZnach[10] %10;          // 3

        SpeedKr[0]= SpeedKruise /100;
        SpeedKr[1]= SpeedKruise %100/10;
        SpeedKr[2]= SpeedKruise %10;
  
      for(byte kr=0; kr<3; kr++){
        if (SpeedKr[kr]!=prevSpeedKr[kr] || obnovitSpeedKr[kr]) {
                obnovitSpeedKr[kr]=true;
            switch (kr) {
                case 0:      
                    if(obnovitSpeedKr[kr]){                // 100
                        obnovitSpeedKr[kr]=false;
                          tft.fillRect(41, 62, 11, 17, BLACK);
                        if(SpeedKruise >99)showmsg1XY(40, 78, 1, &FreeSans12pt7b, SpeedKr[kr]);   //
                    }  
                    break;
                case 1:       
                    if(obnovitSpeedKr[kr]){                // 10
                        obnovitSpeedKr[kr]=false;
                          tft.fillRect(54, 62, 11, 17, BLACK);
                        if(SpeedKruise >9)showmsg1XY(53, 78, 1, &FreeSans12pt7b, SpeedKr[kr]);
                    }
                    break;
                case 2:       
                    if(obnovitSpeedKr[kr]){                // 1
                        obnovitSpeedKr[kr]=false;
                          tft.fillRect(67, 62, 11, 17, BLACK);
                        showmsg1XY(66, 78, 1, &FreeSans12pt7b, SpeedKr[kr]);
                    }
                    break;
            }  
        }
      }
}
void showTextSpeed(){ 
      tft.setTextColor(colorTextSpeed);     
    showmsgXY(48, 96, 1, &FreeSans9pt7b, "km/h");
}
// --------------------------------------------------------------------------------------------------------
void drawScale(){ 
  int k;  
  x1Scale=179, x2Scale=319, yScale=295;   // 170, 328, 295

  for(k=0; k<9; k++){
    if(k==0){
      tft.drawRoundRect(x1Scale, yScale-k*15, 24, 12, 3, BLUE); 
      tft.drawRoundRect(x2Scale, yScale-k*15, 24, 12, 3, RED); 
    }
    if(k==1){
      tft.drawRoundRect(x1Scale-4, yScale-k*15, 24, 12, 3, WHITE); 
      tft.drawRoundRect(x2Scale+4, yScale-k*15, 24, 12, 3, WHITE); 
    }
    if(k==2){
      tft.drawRoundRect(x1Scale-9, yScale-k*15, 24, 12, 3, WHITE); 
      tft.drawRoundRect(x2Scale+9, yScale-k*15, 24, 12, 3, WHITE); 
    }
    if(k==3){
      tft.drawRoundRect(x1Scale-15, yScale-k*15, 24, 12, 3, WHITE); 
      tft.drawRoundRect(x2Scale+15, yScale-k*15, 24, 12, 3, WHITE); 
    }
    if(k==4){
      tft.drawRoundRect(x1Scale-23, yScale-k*15, 24, 12, 3, WHITE); 
      tft.drawRoundRect(x2Scale+23, yScale-k*15, 24, 12, 3, WHITE); 
    }
    if(k==5){
      tft.drawRoundRect(x1Scale-32, yScale-k*15, 24, 12, 3, WHITE); 
      tft.drawRoundRect(x2Scale+32, yScale-k*15, 24, 12, 3, WHITE); 
    }
    if(k==6){
      tft.drawRoundRect(x1Scale-44, yScale-k*15, 24, 12, 3, RED); 
      tft.drawRoundRect(x2Scale+44, yScale-k*15, 24, 12, 3, WHITE); 
    }
    if(k==7){
      tft.drawRoundRect(x1Scale-58, yScale-k*15, 24, 12, 3, RED); 
      tft.drawRoundRect(x2Scale+58, yScale-k*15, 24, 12, 3, WHITE); 
    }
    if(k==8){
      tft.drawRoundRect(x1Scale-76, yScale-k*15, 24, 12, 3, RED); 
      tft.drawRoundRect(x2Scale+76, yScale-k*15, 24, 12, 3, GREEN); 
    }
  }
}

void iconAuto(){
      int x, y;
  if(ScreenBKvariant>=0 && ScreenBKvariant<3) x=192, y=88;
  if(ScreenBKvariant==3 || ScreenBKvariant==4) x=141, y=88;
  
    tft.fillRect(x, y, 30, 2, colorAuto);           // крыша авто
    tft.drawLine(x-3, y+14, x-2, y+4, colorAuto);   // зад
    tft.drawLine(x-2, y+14, x-1, y+1, colorAuto);   // зад
    
    tft.drawLine(x+30, y+1, x+31, y+5, colorAuto);   // лобовое стекло
    tft.drawLine(x+31, y+1, x+32, y+5, colorAuto);   // лобовое стекло
    tft.fillRect(x+32, y+6, 17, 2, colorAuto);       // капот

    tft.drawLine(x+50, y+6, x+52, y+14, colorAuto);   // решетка радиатора
    tft.drawLine(x+51, y+6, x+53, y+14, colorAuto);   // решетка радиатора

    tft.fillRect(x-2, y+15, 3, 2, colorAuto);    // днище
    tft.fillRect(x+18, y+15, 14, 2, colorAuto);   // днище
    tft.fillRect(x+49, y+15, 2, 2, colorAuto);    // днище

    tft.drawCircle(x+9, y+17, 4, colorAuto);     // колесо
    tft.drawCircle(x+9, y+17, 5, colorAuto);     // колесо
    tft.drawCircle(x+40, y+17, 4, colorAuto);     // колесо
    tft.drawCircle(x+40, y+17, 5, colorAuto);     // колесо
}
void iconStation(){
      int x, y, r=9;
  if(ScreenBKvariant>=0 && ScreenBKvariant<3){
    x=145, y=88;
 
    tft.drawCircle(x, y, r, colorAuto);         // точка отсчета
    tft.drawCircle(x, y, r-1, colorAuto);       // точка отсчета
    tft.drawCircle(x, y, r-2, colorAuto);       // точка отсчета
    tft.fillRect(x-1, y+10, 3, 12, colorAuto);  // точка отсчета
  }
}
void iconPoints(){
      int x, y;
  if(ScreenBKvariant>=0 && ScreenBKvariant<3){
    x=155, y=101;

    tft.fillRect(x, y, 5, 5, colorAuto);       // точка 1
    tft.fillRect(x+10, y, 5, 5, colorAuto);    // точка 2
    tft.fillRect(x+20, y, 5, 5, colorAuto);    // точка 3
  }
}
void iconStrelka(){
    int x, y;
  if(ScreenBKvariant==3 || ScreenBKvariant==4){
    x=202, y=73;
  
    tft.fillRect(x, y+28, 5, 5, colorAuto);             // точка 1
    tft.fillRect(x+9, y+28, 5, 5, colorAuto);          // точка 2
    tft.fillRect(x+18, y+28, 4, 5, colorAuto);
    tft.drawLine(x+22, y+25, x+22, y+35, colorAuto);    // стрелка
    tft.drawLine(x+23, y+26, x+23, y+34, colorAuto);
    tft.drawLine(x+24, y+27, x+24, y+33, colorAuto);
    tft.drawLine(x+25, y+28, x+25, y+32, colorAuto);
    tft.drawLine(x+26, y+29, x+26, y+31, colorAuto);
    tft.drawPixel(x+27, y+30, colorAuto);
  }  
//  if(ScreenBKvariant==3)tft.drawBitmap(x+27,y-1,IconBenzin,44,44, colorAuto);   // бензоколонка
  if(ScreenBKvariant==4){
//    tft.drawBitmap(x+27,y-1,IconGaz,44,44, colorAuto);   // газовая колонка
  }
}

void iconAKB(){
    int x=59, y=113;
  for(int t=0; t<2; t++){
    tft.drawRect(x+t, y+t, 36-2*t, 20-2*t, colorAKB);   // незакрашенный прямоугольник
  }
    tft.fillRect(x+6, y-3, 6, 3, colorAKB);
    tft.fillRect(x+6, y+8, 6, 2, colorAKB);
    tft.fillRect(x+24, y-3, 6, 3, colorAKB);
    tft.fillRect(x+24, y+8, 6, 2, colorAKB);
    tft.fillRect(x+26, y+6, 2, 6, colorAKB);
    tft.fillRect(x+25, y+42, 2, 2, colorAKB);
}
void letterStroka(){
    tft.setTextColor(colorAuto);
  if(ScreenBKvariant==0 || ScreenBKvariant==3 || ScreenBKvariant==4)showmsgXY(353, 108, 1, &FreeSans9pt7b, "KM");
  if(ScreenBKvariant==1)showmsgXY(357, 108, 1, &FreeSans12pt7b, "L");
  if(ScreenBKvariant==2){
    showmsgXY(334, 108, 1, &FreeSans12pt7b, "L");
    showmsgXY(348, 108, 1, &FreeSans9pt7b, "/100");
  } 
}
void letterBox(){

      tft.setTextColor(WHITE);
  showmsgXY(126, 240, 1, &FreeSans12pt7b, "o");
  showmsgXY(443, 253, 1, &FreeSans12pt7b, "L");

          tft.setTextColor(RED);  
  showmsgXY(75, 195, 1, &FreeSans12pt7b, "H");
  showmsgXY(357, 305, 1, &FreeSans12pt7b, "E");
    tft.setTextColor(BLUE);
  showmsgXY(147, 305, 1, &FreeSans12pt7b, "C");
    tft.setTextColor(GREEN);
  showmsgXY(430, 195, 1, &FreeSans12pt7b, "F");

    tft.setTextColor(CYAN);
  showmsgXY(420, 131, 1, &FreeSans12pt7b, "G");
  showmsgXY(440, 156, 1, &FreeSans9pt7b, "L");

  int x=187, y=208;
     tft.fillRect(x+70, y-35, 6, 6, colorTime);
     tft.fillRect(x+70, y-20, 6, 6, colorTime);

     tft.setTextColor(colorAKB);
  showmsgXY(107, 156, 1, &FreeSans12pt7b, "v");
}
      
void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg){        // буква
    tft.setFont(f);
    tft.setCursor(x, y);
    tft.setTextSize(sz);
    tft.print(msg);
}
void showmsg1XY(int x1, int y1, int sz1, const GFXfont *f1, byte msg1){         // byte
    tft.setFont(f1);
    tft.setCursor(x1, y1);
    tft.setTextSize(sz1);
    tft.print(msg1);
}
void showmsg2XY(int x2, int y2, int sz2, const GFXfont *f2, word msg2){         // word
    tft.setFont(f2);
    tft.setCursor(x2, y2);
    tft.setTextSize(sz2);
    tft.print(msg2);
}
void showmsg3XY(int x3, int y3, int sz3, const GFXfont *f3, int msg3){          // int
    tft.setFont(f3);
    tft.setCursor(x3, y3);
    tft.setTextSize(sz3);
    tft.print(msg3);
}

void FramePerimeter(){    // рисование линии по-горизонтали
// начало координат из левой верхней точки (гориз, верт, длина линии)

  tft.drawFastHLine(0, 0, 369, GREY);     // верхняя линия
  tft.drawFastHLine(31, 319, 439, GREY);  // нижняя линия
                                  // верхняя ломаная линия слева-направо
  tft.drawFastHLine(33, 104, 65, GREY);   
  tft.drawFastHLine(138, 123, 246, GREY);
  tft.drawFastHLine(424, 104, 24, GREY);
                                  // нижняя ломаная линия слева-направо
  tft.drawFastHLine(45, 165, 73, GREY); 
  tft.drawFastHLine(191, 133, 140, GREY); 
  tft.drawFastHLine(403, 165, 69, GREY);    
  
// рисование линии по-вертикали   
  for(int y=0; y<319; y++){             // левая линия
    int x;
    if(y<20)x=0;                        // 0                              
    if(y>=20 && y<40)x=(y-20)/2;        // 10
    if(y>=40 && y<80)x=10+(y-40)/2.5;   // 26
    if(y>=80 && y<140)x=26+(y-80)/4;    // 41
    if(y>=140 && y<185)x=41+(y-140)/7;  // 47
    if(y>=185 && y<215)x=48;            // 48
    if(y>=215 && y<260)x=48-(y-215)/9;  // 43
    if(y>=260 && y<319)x=43-(y-260)/5;  // 31
      tft.drawPixel(x, y, GREY);        // (гориз, верт) x, y
  }
    
  for(int y=0; y<320; y++){               // правая линия
    int x;
    if(y<32)x=370+y;                      // 402    
    if(y>=32 && y<68)x=402+(y-32)/1.3;    // 429
    if(y>=68 && y<103)x=429+(y-68)/1.8;   // 448
    if(y>=103 && y<135)x=448+(y-103)/2.2; // 462
    if(y>=135 && y<174)x=462+(y-135)/3;   // 475
    if(y>=174 && y<210)x=475+(y-174)/9;   // 479
    if(y>=210 && y<260)x=479;             // 479
    if(y>=260 && y<319)x=479-(y-260)/6;   // 470 
      tft.drawPixel(x, y, GREY);           // (гориз, верт) x, y
  }
} 

void DugaMax(){
    xx=114, yy=166;           // 137, 165
    xt=1, yt=-1;              // координата x-увеличивается, y-уменьшается
  sectorDuga();

    xx=408, yy=166;           // 384, 165
    xt=-1, yt=-1;              // координата x-увеличивается, y-уменьшается
  sectorDuga();

    xx=194, yy=132;           // 108, 104
    xt=-1, yt=1;
  DugaDop();
  
    xx=328, yy=132;           // 108, 104
    xt=1, yt=1; 
  DugaDop();     
}

void DugaMin(){
    xx=95, yy=103;           // 108, 104
    xt=1, yt=1;              // координата x-увеличивается, y-уменьшается
  sectorDuga();
    
    xx=141, yy=124;           // 128, 124
    xt=-1, yt=-1;              // координата x-увеличивается, y-уменьшается
  sectorDuga();

    xx=381, yy=124;           // 394, 124
    xt=1, yt=-1;              // координата x-увеличивается, y-уменьшается
  sectorDuga();

    xx=427, yy=103;           // 414, 104
    xt=-1, yt=1;              // координата x-увеличивается, y-уменьшается
  sectorDuga();
}

void sectorDuga(){
  tft.drawFastHLine(xx+xt*1, yy+yt*1, xt*5, colorDuga);
  tft.drawFastHLine(xx+xt*6, yy+yt*2, xt*3, colorDuga);
  tft.drawFastHLine(xx+xt*9, yy+yt*3, xt*3, colorDuga);
  tft.drawFastHLine(xx+xt*12, yy+yt*4, xt*2, colorDuga);
  tft.drawFastHLine(xx+xt*14, yy+yt*5, xt*2, colorDuga);
  tft.drawFastHLine(xx+xt*16, yy+yt*6, xt*2, colorDuga);
  tft.drawFastHLine(xx+xt*18, yy+yt*7, xt*2, colorDuga);
  tft.drawFastHLine(xx+xt*20, yy+yt*8, xt*1, colorDuga);  
  tft.drawFastHLine(xx+xt*21, yy+yt*9, xt*1, colorDuga); 
  tft.drawFastHLine(xx+xt*22, yy+yt*10, xt*1, colorDuga);    
}

void DugaDop(){
    tft.drawFastHLine(xx+xt*2, yy+yt*1, xt*8, colorDuga);
    tft.drawFastHLine(xx+xt*10, yy+yt*2, xt*5, colorDuga);
    tft.drawFastHLine(xx+xt*15, yy+yt*3, xt*4, colorDuga);
    tft.drawFastHLine(xx+xt*19, yy+yt*4, xt*3, colorDuga);
    tft.drawFastHLine(xx+xt*22, yy+yt*5, xt*3, colorDuga);
    tft.drawFastHLine(xx+xt*25, yy+yt*6, xt*3, colorDuga);
    tft.drawFastHLine(xx+xt*28, yy+yt*7, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*30, yy+yt*8, xt*3, colorDuga);
    tft.drawFastHLine(xx+xt*33, yy+yt*9, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*35, yy+yt*10, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*37, yy+yt*11, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*39, yy+yt*12, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*41, yy+yt*13, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*43, yy+yt*14, xt*1, colorDuga);
    tft.drawFastHLine(xx+xt*44, yy+yt*15, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*46, yy+yt*16, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*48, yy+yt*17, xt*1, colorDuga);
    tft.drawFastHLine(xx+xt*49, yy+yt*18, xt*1, colorDuga);
    tft.drawFastHLine(xx+xt*50, yy+yt*19, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*52, yy+yt*20, xt*1, colorDuga);
    tft.drawFastHLine(xx+xt*53, yy+yt*21, xt*1, colorDuga);
    tft.drawFastHLine(xx+xt*54, yy+yt*22, xt*2, colorDuga);
    tft.drawFastHLine(xx+xt*56, yy+yt*23, xt*1, colorDuga);
}
//*******************************************************************************************************
/* Recode russian fonts from UTF-8 to Windows-1251 */
String utf8rus(String source){
      int i, k;
      String target;
      unsigned char n;
      char m[2] = { '0', '\0' };
    k = source.length(); i = 0;
  while (i < k) {
      n = source[i]; i++;
    if(n >= 0xC0){
      switch (n){
        case 0xD0: {
              n = source[i]; i++;
            if (n == 0x81){
              n = 0xA8;
                break;
            }
            if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
              break;
          }
        case 0xD1: {
              n = source[i]; i++;
            if(n == 0x91){
              n = 0xB8;
                break;
            }
            if(n >= 0x80 && n <= 0x8F) n = n + 0x70;
              break;
          }
      }
    }
      m[0] = n; target = target + String(m);
  }
    return target;
}
//************************************* END *************************************************************

 

lev2606
Offline
Зарегистрирован: 19.06.2019

Сори, не на тот проект ссылка была! вот правильная

https://disk.yandex.ru/d/iUhOyLVEkkjgrQ

MaksVV
Offline
Зарегистрирован: 06.08.2015
lev2606
Offline
Зарегистрирован: 19.06.2019

привет, Макс! Проверил тобой измененный скетч, работает. Выкладываю лог. В нем есть сбои ответов- это я переходил в меню и перебирал в нем пункты.

13:03:35.451 -> Fast init 25msLOW 25msHIGH
13:03:35.451 -> 
13:03:35.451 ->                Send to PCM:  81 11 F1 81 4 
13:03:35.451 -> Receive from PCM: 83 F1 11 C1 EF 8F C4            CheckSUM good!
13:03:35.451 -> 
13:03:35.451 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:35.732 -> CM:  82 11 F1 21 2 A7 
13:03:35.779 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 72 0 4 72 D1 70 45 54 13 8C 10 48 4 25 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 1A            CheckSUM good!
13:03:35.966 -> 
13:03:35.966 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:36.013 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 74 0 4 6C D1 70 45 8E 13 A4 10 48 4 28 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 6B            CheckSUM good!
13:03:36.247 -> 
13:03:36.247 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:36.294 -> 52 5F 0 79 0 4 6C D1 70 45 98 13 A8 10 48 4 29 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 7F            CheckSUM good!
13:03:36.482 -> 
13:03:36.482 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:36.528 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 74 0 4 6D D1 70 45 A3 13 A8 10 48 4 25 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 82            CheckSUM good!
13:03:36.716 -> 
13:03:36.716 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:36.763 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 77 0 4 6F D1 70 45 6F 13 8C 10 48 4 1F 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 31            CheckSUM good!
13:03:36.997 -> 
13:03:36.997 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:37.044 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 74 0 4 6E D1 70 45 14 13 84 10 48 4 18 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 C3            CheckSUM good!
13:03:37.232 -> 
13:03:37.232 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:37.278 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 7A 0 4 73 D1 70 44 FC 13 7D 10 48 4 18 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 AE            CheckSUM good!
13:03:37.513 -> 
13:03:37.513 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:37.513 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 73 0 4 6F D1 70 44 DF 13 6C 10 48 4 14 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 71            CheckSUM good!
13:03:37.747 -> 
13:03:37.747 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:37.794 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 7A 0 4 71 D1 70 44 C5 13 72 10 48 4 12 0 0 0 0 0 0 0 1 7F 0 0 0 0 
13:03:37.981 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:38.028 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 78 0 4 70 D1 70 44 DD 13 68 10 48 4 10 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 6D            CheckSUM good!
13:03:38.403 -> 
13:03:38.403 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:38.450 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 79 0 4 6E D1 70 44 EB 13 75 10 48 4 D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 84            CheckSUM good!
13:03:38.684 -> 
13:03:38.684 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:38.731 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 74 0 4 6C D1 70 44 F7 13 83 10 48 4 F 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 99            CheckSUM good!
13:03:38.918 -> 
13:03:38.918 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:38.965 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 74 0 4 6C D1 70 44 F2 13 81 10 48 4 E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 91            CheckSUM good!
13:03:39.200 -> 
13:03:39.200 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:39.200 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 75 0 4 77 D1 70 44 B6 13 69 10 48 4 843            CheckSUM good!
13:03:39.528 -> 
13:03:39.528 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:39.575 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 78 0 4 6A D1 70 44 1D 13 26 10 48 3 F6 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 4B            CheckSUM good!
13:03:39.762 -> 
13:03:39.762 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:39.809 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 75 0 4 66 D1 70 44 60 13 38 10 48 3 F1 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 93            CheckSUM good!
13:03:40.043 -> 
13:03:40.043 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:40.090 -> Receive from PCM: A2 F1 11 61 2 52 5F 0 76 0 4 6F D1 70 44 48 13 36 10 48 3 F3 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 85            CheckSUM good!
13:03:40.278 -> 
13:03:40.278 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:40.324 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 75 0 4 6A D1 70 44 20 13 26 10 48 3 EF 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 44            CheckSUM good!
13:03:40.559 -> 
13:03:40.559 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:40.559 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 78 0 4 60 D1 70 44 7 13 2F 10 48 3 E9 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 27            CheckSUM good!
13:03:40.793 -> 
13:03:40.793 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:40.840 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 77 0 4 65 D1 70 43 FF 13 2D 10 48 3 EA 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 21            CheckSUM good!
13:03:41.027 -> 
13:03:41.027 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:41.074 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 7A 0 4 60 D1 70 44 A 13 30 10 48 3 E9 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 2D            CheckSUM good!
13:03:41.309 -> 
13:03:41.309 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:41.356 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 78 0 4 62 D1 70 44 2 13 24 10 48 3 E4 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 14            CheckSUM good!
13:03:41.543 -> 
13:03:41.543 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:41.590 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 79 0 4 63 D1 70 43 F7 13 33 10 48 3 E7 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 1C            CheckSUM good!
13:03:43.417 -> 
13:03:43.417 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:43.417 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 77 0 4 68 D1 70 43 E 12 B7 10 48 3 B2 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 84            CheckSUM good!
13:03:43.652 -> 
13:03:43.652 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:43.699 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 79 0 4 64 D1 70 42 D5 12 B1 10 48 3 A7 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 37            CheckSUM good!
13:03:43.886 -> 1 F1 21 2 A7 
13:03:43.933 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 70 0 4 61 D1 70 42 E0 12 AB 10 48 3 9D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 26            CheckSUM good!
13:03:44.167 -> 
13:03:44.167 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:44.214 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 7A 0 4 5D D1 70 42 F0 12 AB 10 48 3 98 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 37            CheckSUM good!
13:03:44.542 -> 
13:03:44.542 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:44.542 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 7A 0 4 65 D1 70 42 D2 12 AC 10 48 3 8A 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 14            CheckSUM good!
13:03:44.776 -> 
13:03:44.776 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:44.964 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 75 0 4 5F D1 70 42 D2 12 AF 10 48 3 85 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 7            CheckSUM good!
13:03:45.010 -> 
13:03:45.010 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:45.057 -> Receive from PCM: A2 F1 11 61 2 53 5F 0 7A 0 4 63 D1 70 42 D2 12 B5 10 48 3 7B 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 
13:03:45.292 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:45.292 -> 2 A7            CheckSUM fail!!!
13:03:45.339 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 78 0 4 63 D1 70 42 98 12 8B 10 48 3 6B 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 97            CheckSUM good!
13:03:45.573 -> 1 21 2 A7 
13:03:45.573 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 76 0 4 5F D1 70 42 2E 12 73 10 48 3 60 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 4            CheckSUM good!
13:03:45.995 -> 
13:03:45.995 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:46.042 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 79 0 4 55 D1 70 42 4E 12 63 10 48 3 4D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 FA            CheckSUM good!
13:03:46.276 -> 
13:03:46.276 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:46.323 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 75 0 4 55 D1 70 42 59 12 66 10 48 3 46 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 FD            CheckSUM good!
13:03:46.510 -> 
13:03:46.510 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:46.557 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 79 0 4 51 D1 70 42 85 12 87 10 48 3 41 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 45            CheckSUM good!
13:03:46.791 -> 
13:03:46.791 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:46.838 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 75 0 4 4D D1 70 42 A6 12 8D 10 48 3 3A 0 0 0 0 0 0 0 1 7ood!
13:03:47.026 -> 
13:03:47.026 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:47.072 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 79 0 4 51 D1 70 42 B4 12 99 10 48 3 35 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 7A            CheckSUM good!
13:03:47.682 -> 
13:03:47.682 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:47.728 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 77 0 4 4D D1 70 42 A1 12 8B 10 48 3 1B 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 39            CheckSUM good!
13:03:47.963 -> 
13:03:47.963 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:47.963 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 7B 0 4 4C D1 70 42 98 12 8D 10 48 3 14 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 2E            CheckSUM good!
13:03:48.197 -> 
13:03:48.197 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:48.244 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 72 0 4 4D D1 70 42 30 12 78 10 48 3 9 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 9E            CheckSUM good!
13:03:48.431 -> 
13:03:48.431 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:48.478 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 79 0 4 42 D1 70 42 36 12 64 10 48 3 1 0 0 0 0 0 0 0 1 7Food!
13:03:48.712 -> 
13:03:48.712 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:48.712 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 79 0 4 41 D1 70 42 C4 12 9C 10 48 3 9 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 51            CheckSUM good!
13:03:49.134 -> 
13:03:49.134 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:49.134 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 7B 0 4 41 D1 70 43 19 12 BA 10 48 3 D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 CB            CheckSUM good!
13:03:49.369 -> 
13:03:49.369 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:49.415 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 75 0 4 43 D1 70 43 3F 12 C1 10 48 3 E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 F5            CheckSUM good!
13:03:49.603 -> 
13:03:49.603 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:49.650 -> Receive from PCM: A2 F1 11 61 2 BB 10 48 3 D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E5            CheckSUM good!
13:03:49.884 -> 
13:03:49.884 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:49.931 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 75 0 4 46 D1 70 43 37 12 B1 10 48 3 C 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 DE            CheckSUM good!
13:03:50.493 -> 
13:03:50.493 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:50.540 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 74 0 4 44 D1 70 43 3A 12 BB 10 48 3 D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E9            CheckSUM good!
13:03:50.774 -> 
13:03:50.774 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:50.774 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 77 0 4 41 D1 70 43 58 12 BB 10 48 3 D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 7            CheckSUM good!
13:03:51.009 -> 
13:03:51.009 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:51.056 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 78 0 4 3D D1 70 43 76 12 C0 10 48 3 14 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 2E            CheckSUM good!
13:03:51.243 -> 
13:03:51.243 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:51.290 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 7B 0 4 41 D1 70 43 7C 12 C9 10 48 3 16 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 46            CheckSUM good!
13:03:51.524 -> 
13:03:51.524 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:51.571 -> Receive from PCM: A2 F1 11 61 2 54 5F 0 79 0 4 47 D1 70 43 73 12 C3 10 48 3 E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 33            CheckSUM good!
13:03:51.758 -> 21 2 A7 
13:03:51.805 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 7A 0 4 40 D1 70 43 5D 12 C1 10 48 3 D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 15            CheckSUM good!
13:03:52.040 -> 
13:03:52.040 ->                Send to PCM:  81 21 2 A7 
13:03:52.040 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 7A 0 4 40 D1 70 43 5B 12 C1 10 48 3 6 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 C            CheckSUM good!
13:03:52.274 -> 
13:03:52.274 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:52.321 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 71 0 4 48 D1 70 43 50 12 C9 10 48 3 7 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 9            CheckSUM good!
13:03:52.555 -> 
13:03:52.555 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:52.602 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 7A 0 4 37 D1 70 43 63 12 D2 10 48 3 F 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 25            CheckSUM good!
13:03:52.789 -> 
13:03:52.789 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:52.836 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 78 0 4 3A D1 70 43 B0 12 DF 10 48 3 10 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 81            CheckSUM good!
13:03:53.071 -> 
13:03:53.071 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:53.071 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 7B 0 4 3F D1 70 43 B0 12 E1 10 48 3 B 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 86            CheckSUM good!
13:03:53.586 -> 
13:03:53.586 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:53.633 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 76 0 4 35 D1 70 43 CB 12 E5 10 48 3 27 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 B2            CheckSUM good!
13:03:53.820 -> 
13:03:53.820 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:53.867 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 7A 0 4 39 D1 70 44 5 12 EB 10 48 3 31 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 5            CheckSUM good!
13:03:54.101 -> 
13:03:54.101 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:54.101 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 74 0 4 44 D1 70 43 D6 12 F1 10 48 3 34 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E3            CheckSUM good!
13:03:54.664 -> 
13:03:54.664 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:54.711 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 75 0 4 4F D1 70 43 5D 12 C7 10 48 3 37 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 4F            CheckSUM good!
13:03:54.945 -> 
13:03:54.945 ->                Send to PCM:  81 21 2 A7 
13:03:54.945 -> Receive from PCM: A2 F1 11 61 2 B2 10 48 3 1B 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E9            CheckSUM good!
13:03:55.179 -> 
13:03:55.179 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:55.226 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 6D 0 4 48 D1 70 43 14 12 B4 10 48 3 12 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 BF            CheckSUM good!
13:03:55.413 -> 
13:03:55.413 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:55.460 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 71 0 4 44 D1 70 43 42 12 BE 10 48 3 B 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 F0            CheckSUM good!
13:03:55.695 -> 
13:03:55.695 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:55.742 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 74 0 4 43 D1 70 43 6B 12 D2 10 48 3 8 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 2C            CheckSUM good!
13:03:55.929 -> 
13:03:55.929 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:55.976 -> Receive from PCM: A2 F1 11 61 2 D9 10 48 3 A 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 5D            CheckSUM good!
13:03:56.632 -> 
13:03:56.632 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:56.632 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 7A 0 4 40 D1 70 44 5E 13 1E 10 48 3 3B 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A3            CheckSUM good!
13:03:56.866 -> 
13:03:56.866 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:56.913 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 7B 0 4 4A D1 70 44 59 13 20 10 48 3 3E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 AE            CheckSUM good!
13:03:57.100 -> 
13:03:57.100 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:57.147 -> Receive from PCM: A2 F1 11 61 2 55 5F 0 78 0 4 54 D1 70 43 D3 12 F3 10 48 3 41 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 3            CheckSUM good!
13:03:57.382 -> 
13:03:57.382 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:57.428 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 7B 0 4 57 D1 70 43 3 12 9D 10 48 3 3A 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 DD            CheckSUM good!
13:03:57.616 -> 
13:03:57.616 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:57.663 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 79 0 4 4B D1 70 42 FB 12 9D 10 48 3 36 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 C2            CheckSUM good!
13:03:57.850 -> 
13:03:57.850 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:57.897 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 74 0 4 4D D1 70 42 EA 12 A6 10 48 3 22 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A3            CheckSUM good!
13:03:58.131 -> 
13:03:58.131 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:59.022 -> Receive from PCM: A2 
13:03:59.022 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:59.022 -> 0  MessageReset
13:03:59.022 -> Receive from PCM: 73 0  MessageReset
13:03:59.022 -> Receive from PCM: 4 3B  MessageReset
13:03:59.022 -> Receive from PCM: D1 70  MessageReset
13:03:59.022 -> Receive from PCM: 43 29  MessageReset
13:03:59.022 -> Receive from PCM: 12 C3  MessageReset
13:03:59.022 -> Receive from PCM: 10 48  MessageReset
13:03:59.068 -> Receive from PCM: 3 25  MessageReset
13:03:59.068 -> Receive from PCM: 1 7F  MessageReset
13:03:59.068 -> Receive from PCM: F0 82  MessageReset
13:03:59.068 -> Receive from PCM: 11 F1 21  MessageReset
13:03:59.068 -> Receive from PCM: 2 A7  MessageReset
13:03:59.068 -> Rece6 0 4 3C D1 70 43 B8 12 D9 10 48 3 D 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 81            CheckSUM good!
13:03:59.256 -> 
13:03:59.256 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:59.303 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 79 0 4 35 D1 70 43 F1 12 DE 10 48 3 1C 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 CA            CheckSUM good!
13:03:59.537 -> 
13:03:59.537 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:59.537 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 79 0 4 37 D1 70 43 FF 12 F1 10 48 3 28 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 F9            CheckSUM good!
13:03:59.771 -> 
13:03:59.771 ->                Send to PCM:  82 11 F1 21 2 A7 
13:03:59.818 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 76 0 4 3E D1 70 43 FC 12 EA 10 48 3 2E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 F9            CheckSUM good!
13:04:00.006 -> 
13:04:00.006 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:00.053 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 7B 0 4 40 D1 70 43 D9 12 EB 10 48 3 37 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E7            CheckSUM good!
13:04:00.287 -> 
13:04:00.287 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:00.334 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 76 0 4 4E D1 70 43 79 12 D5 10 48 3 36 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 79            CheckSUM good!
13:04:02.536 -> 
13:04:02.536 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:02.536 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 7A 0 4 35 D1 70 42 CC 12 A2 10 48 3 6 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 53            CheckSUM good!
13:04:02.771 -> 
13:04:02.771 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:02.817 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 76 0 4 29 D1 70 43 3D 12 CF 10 48 3 6 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E3            CheckSUM good!
13:04:03.005 -> 
13:04:03.005 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:03.052 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 7A 0 4 31 D1 70 43 CE 12 F9 10 48 3 1E 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 C2            CheckSUM good!
13:04:03.286 -> 
13:04:03.286 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:03.333 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 75 0 4 30 D1 70 44 18 12 FF 10 48 3 28 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 16            CheckSUM good!
13:04:03.520 -> 
13:04:03.520 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:03.567 -> Receive from PCM: A2 F1 11 61 2 56 5F 0 7B 0 4 36 D1 70 44 33 13 9 10 48 3 31 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 51            CheckSUM good!
13:04:03.801 -> 
13:04:03.801 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:03.801 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 75 0 4 3C D1 70 44 A 12 F7 10 48 3 36 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 1B            CheckSUM good!
13:04:04.036 -> 
13:04:04.036 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:04.083 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 79 0 4 3B D1 70 43 FC 12 F7 10 48 3 3F 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 18            CheckSUM good!
13:04:04.270 -> 
13:04:04.270 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:04.317 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 74 0 4 42 D1 70 43 D6 12 E2 10 48 3 43 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 E3            CheckSUM good!
13:04:04.551 -> 
13:04:04.551 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:04.598 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 7A 0 4 44 D1 70 43 AA 12 E1 10 48 3 45 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 C0            CheckSUM good!
13:04:04.785 -> 
13:04:04.785 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:04.832 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 76 0 4 45 D1 70 43 92 12 D6 10 48 3 4C 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 A1            CheckSUM good!
13:04:05.067 -> 
13:04:05.067 ->                Send to PCM:  82 11 F1 21 2 A7 
13:04:05.067 -> Receive from PCM: A2 F1 11 61 2 57 5F 0 7B 0 4 42 D1 70 43 87 12 C9 10 48 3 4F 0 0 0 0 0 0 0 1 7F 0 0 0 0 0 0 8E 

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

ну супер. теперь там чуть выше функции setup(), где дефайны по клайн, DEBUG_KLINE закомментируй, а DEBUG_VALUES можешь раскомментить, чтобы проверить как формулы правильно или нет работают. Во вкладке K_line.h функция DEBUGPrint можешь добавить переменных своих для отображения. После того как проект будет к завершению, скомпилируй скетч с закомментированными и DEBUG_KLINE и DEBUG_VALUES, чтобы откладка в терминал больше не шла, не мешала работе и лишнюю память и процессорное время не отъедала. 

 

lev2606
Offline
Зарегистрирован: 19.06.2019

ок, спасибо, Макс! 

lev2606
Offline
Зарегистрирован: 19.06.2019

всем привет! яможет кто подскажет про монитор порта ардуино. Столкнулся с тем, что отсечки времени в мониторе не соответствуют временным и интервалам и задержкам ардуино!!! Проверял интервалы общения БК с ЭБУ авто и выявил то, что вместо интервала в 100 мСек- 94, а вместо 60 мСек - 47!!! Причем 60 увеличиваю до 70 - все равно 47!!! Стало интересно, попробовал Blink с delay и без delay , то же самое. Если сделать еще больше - начнет скакать, то 47, то больше 80-ти. Плата Мега, пробовал на 115200 и 9600 - одинаково!

const int ledPin = 13;

bool led_state = 0; // начальное состояние светодиода - выключен

void setup(){
  Serial.begin(9600);
  Serial.println("Test OK!");  
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, led_state); // гасим светодиод
}

void loop(){
    if( led_state ) led_state = !led_state;
        delay(60);
      Serial.println("60");  
      digitalWrite(ledPin, led_state); 
    if( !led_state ) led_state = !led_state;
        delay(100);
      Serial.println("100");
      digitalWrite(ledPin, led_state);
}
const int ledPin = 13;                // номер штыря светодиода

int ledState = LOW;                   // ledState used to set the LED
unsigned long previousMillis = 0;     // will store last time LED was updated
const long interval = 60;           // interval at which to blink (milliseconds)

void setup(){
  Serial.begin(9600);
  Serial.println("Test OK!");  
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, ledState);  // гасим светодиод
}

void loop(){
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis >= interval){   
    previousMillis = currentMillis;
  
    if(ledState == LOW){
      ledState = HIGH;
    }else{
      ledState = LOW;
    }

    digitalWrite(ledPin, ledState);
        delay(50);
      Serial.println(ledState);
  }
}

во втором скетче даже delay добавлял до 10 мСек- не помогает. Добавил 50 - задержки стали скакать.

lev2606
Offline
Зарегистрирован: 19.06.2019
08:19:17.537 -> Test OK!
08:19:17.584 -> 60
08:19:17.678 -> 100
08:19:17.771 -> 60
08:19:17.865 -> 100
08:19:17.912 -> 60
08:19:18.006 -> 100
08:19:18.052 -> 60
08:19:18.193 -> 100
08:19:18.240 -> 60
08:19:18.334 -> 100
08:19:18.380 -> 60
08:19:18.474 -> 100
08:19:18.568 -> 60
08:19:18.662 -> 100
08:19:18.709 -> 60
08:19:18.802 -> 100
08:19:18.896 -> 60
08:19:18.990 -> 100
08:19:19.037 -> 60
08:19:19.130 -> 100
08:19:19.224 -> 60
08:19:19.318 -> 100
08:19:19.365 -> 60
08:19:19.458 -> 100
08:19:19.505 -> 60
08:19:19.646 -> 100
08:19:19.693 -> 60
08:19:19.786 -> 100
08:19:19.833 -> 60
08:19:19.927 -> 100
08:19:20.021 -> 60
08:19:20.114 -> 100
08:19:20.161 -> 60
08:19:20.255 -> 100
08:19:20.349 -> 60
08:19:20.442 -> 100
08:19:20.489 -> 60
08:19:20.583 -> 100
08:19:20.677 -> 60
08:19:20.770 -> 100
08:19:20.817 -> 60
08:23:56.433 -> 1
08:23:56.480 -> 0
08:23:56.574 -> 1
08:23:56.620 -> 0
08:23:56.667 -> 1
08:23:56.761 -> 0
08:23:56.808 -> 1
08:23:56.855 -> 0
08:23:56.901 -> 1
08:23:56.995 -> 0
08:23:57.042 -> 1
08:23:57.089 -> 0
08:23:57.183 -> 1
08:23:57.230 -> 0
08:23:57.276 -> 1
08:23:57.323 -> 0
08:23:57.417 -> 1
08:23:57.464 -> 0
08:23:57.511 -> 1
08:23:57.605 -> 0
08:23:57.651 -> 1
08:23:57.698 -> 0
08:23:57.745 -> 1
08:23:57.839 -> 0
08:23:57.886 -> 1
08:23:57.933 -> 0
08:23:58.020 -> 1
08:23:58.066 -> 0

это логи Blink-ов

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

вставь свой таймштамп на миллис , а идэшный убери в настройках 

lev2606
Offline
Зарегистрирован: 19.06.2019

ну вот, исчезли 7 моих сообщений

lev2606
Offline
Зарегистрирован: 19.06.2019

В общем я уменьшил задержку до 100 мкСек (до 0 не стал уменьшать- боюсь будет нестабильный запрос), теперь запрос = 1 мСек и обработка ответа = 1 мСек!!! Запросы и ответы стабильны! Спасибо, Макс, за подсказку!

lev2606
Offline
Зарегистрирован: 19.06.2019

привет всем! По многочисленным просьбам трудящихся переделал язык Меню на русский. Увеличил кол-во символов в строке до 14, стали читабельны почти все надписи. Перешел с 3-го размера шрифта на 2-й, так кол-во символов увеличилось в 1,5 раза и стали доступны нормальные названия пунктов Меню на русском, прямо как в оригинале! Но оказалось что мне уже плохо видно 2-й шрифт с расстояния 70-80 см, приходится напрягать зрение и отвлекаться. Так что пришлось отказаться от этого размера. Еще сделал ввод даты, т.к. оказалось что нужно знать дату для некоторых сообщений, например для сообщения для замены резины на зимнюю!))). Но начал подтормаживать энкодер, оказалось что от русификатора tft.cp437. В общем, пришлось пока отказаться от использования русских надписей! Пока допиливаю Меню, хочу еще сделать чтение и сброс ошибок и чтение данных из ответа ЭБУ (на экране БК) для отладки на месте. (просто у меня есть возможность в пунктах меню изменить некоторые интервалы связи с ЭБУ, корректировать для расчета длительность импульсов впрыска, калибровать датчики и тд.)

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Вы пассажиром в авто передвигаетесь ?

lev2606
Offline
Зарегистрирован: 19.06.2019

понимаю сарказм. Это мой первый БК. До конца не представляю что понадобится отображать, насколько стабильно будет работать связь с ЭБУ в разных режимах авто, скачках напряжения и помехах. Пытаюсь предусмотреть возможность настройки некоторых параметров на месте. Да и хочется задействовать обе страницы Меню (12 пунктов), не зря же я мучился чтобы так сделать! Мне нравится как получилось, хотя для уже отлаженного БК можно сделать Меню одностраничное (сгруппировать некоторые пункты).

lev2606
Offline
Зарегистрирован: 19.06.2019

Вот ведь! Оказывается русский шрифт БК не помеха!!! ))) Всегда интересовало, если на старуху бывает проруха, то что на старика бывает??? ) Буду дальше искать причину глюков энкодера

lev2606
Offline
Зарегистрирован: 19.06.2019

Всем привет. Забыл сразу написать, причиной глюков энкодера было использование монитора порта. Вобщем при проверке работы энкодера монитор порта лучше отключать! А вообще, проект в очередной раз заброшен, слишком я его усложнил лишними примочками! Есть надежда его упростить и наконец закончить, т.к. пока еще езжу на Нексии! )))