Я имел ввиду попробовать новый код и сделать лог. Модернизировать старый код плохая затея он не оптимален и будет тормозить программу даже без задержки delay (100). Т. К. Он пытается принять все сообщение сразу за один проход луп. А без delay, возможно сообщение будет разрезано на 2 или более и тогда каша. Переделывать с новым кодом то минимум, формулы все те-же вставишь, только с номерами байт принятого сообщения немного подправить возможно придётся.
Макс, у меня в коде нет ни одного прерывания, поэтому изъятие байт из Serial-а прерываться не будет. И чем хорош твой код из 157 сообщения, я извлекаю байты из Serial-а не со скоростью 10400 бод, как он посылает, а с максимальной скоростью процессора(это примерно 50 мкСек на байт). Поэтому чтобы изъять все сообщение мне нужно будет не более 2 мСек! Этого даже энкодер не заметит!!!
ну поступай как знаешь . Тебе предложили более лучший вариант, вставить его в текущий код не проблема. Причина сопротивления непонятна. Тот код корявый , это я тебе как автор говорю. Если не будешь его применять . просто проверь хотябы #2185 как работает, изменив тот список пидов на свой один 2102. и машина какая напиши.
ок, Макс, я попробую. Ты не обижайся, просто я не программист, я электронщик, и мне придется много времени потратить чтобы все собрать в одно по твоему новому варианту. Но я это обязательно сделаю! А пока проверю мою версию, сколько времени уходит на подпрограмму Recieve(). Макет БК собран, можно проводить полноценные эксперименты связи с ЭБУ. Кстати, я попробую твой новый код для начала отдельно, без интеграции в БК, так будет проще. Спасибо за помощь! ))) Машина Нексия N-150, с 16-ти клапанным двигателем и ЭБУ Sirius D42
а че мне обижаться, это было скорее раздражение. я пытался тебе объяснить преимущества нового подхода, а ты мне про нет прерываний и что извлекаются байты из буфера уарт со скоростью процессора. А как быстро эти байты туда попадают? правильно, со скоростью 10400. весь ответ ЭБУ из 38 байт туда попадет примерно через 36 мс. как только первый байт туда попал, начинается работа функции receive() , поэтому задержка 100 мс и нужна чтобы дождаться остальные байты, ну или вариации были без нее , всё равно дожидаясь остальных байт функция работает, а это 36 мс. Не комильфо, я щитаю . То что попробуешь, это правильно. Если заработает, думаю лучше потратить время и перейти на новый вариант.
вот засада! Не могу подключиться к ЭБУ! Новый распаянный макет не подключается, раньше подключался с макетом на штырьках- и все работало! У меня в новом макете даже все детали K-Line адаптера с того макета. Правда раньше была плата Uno, а теперь Mega. на Меге пробовал подключиться и с Serial2 и с SoftSerial (на те же выводы чтобы не перепаивать). Нет инициализации и все тут! Проверил работу адаптера- выдает и 0, и 1 (когда соответствующий сигнал на входе). Пробовал соединение ELM327 через блютуз на телефон-все работает, соединение с ЭБУ в норме! Аж остатки мозга закипели!!! ))) Шился скетчем из 157 поста, который раньше у меня работал и с него делал несколько логов. Вот такие дела!
если что, на всякий скажу, что разница софтсериала и хардсериала есть, в контексте работы с к-линией. При работе через софтсериал отправленные байты НЕ прилетают обратно в приемник (эффекта эхо нет), а при работе через хардсериал прилетают (эффект эхо присутствует). Это надо учитывать в скетче. Не факт что причина у тебя в этом , но чтоб знал. В скетче #2185 есть эта настройка (8 строка) .
ну вот, наконец-то заработала связь с ЭБУ! Спасибо Максу! Заработало на сериале3 (14 и 15 выводы меги), но перед этим я пробовал на этих же выводах софт сериал - не стало работать, хотя на этих выводах pcint имеется! Ну и ладно, мне в общем-то сериал и нужен, чтобы прием данных происходил независимо от того, чем сейчас занимается процессор. Пришлось только буфер на 6 байт увеличить, чтобы еще и эхо принимать. Ну теперь уже можно полноценно опробовать макет БК! Завтра постараюсь устроить тест-драйв! ))). Вот лог с выключенным двигателем, но включенным зажиганием (с работающим двигателем лог не сохранился)
протестировал на БК, прикольно смотреть как повышается температура двигателя и изменяется напряжение бортовой сети! ))) Теперь нужно все доводить до ума. Кстати, посчитал что интервал опроса в 150 мСек маловат (со всеми интервалами по официальному протоколу) , возможны глюки. Поэтому увеличиваю интервал опроса до 200 мСек. Посмотрим как будут себя вести интервалы загрузки значков, экрана, меню, а главное не будет ли глючить энкодер!
и скинь часть скетча где все формулы , я тебе их запихаю в свой скетч . дело 2х минут. потом в своём проекте удалишь все, что касается клайн . Вставишь в луп функцию k_line() и заинклюдишь файл "K_lineNexia_sirius.h" (я тебе в него упакую свой скетч), я думаю тогда у тебя это не полгода займет, а несколько минут.
Макс, разобрался в том, что ты мне написал, только один вопрос: про какие формулы идет речь? Формулы преобразования данных, получаемых через Клайн? и формулы расчета расхода топлива?
Макс, у меня в проекте 9 файлов подпрограмм, не считая файлов с логотипом, значками и др. Если я эти 9 файлов просто соберу в один, то получится портянка длиной в 3000 строк! Попробую некоторые подпрограммы убрать или сделать пустыми.
ну супер. теперь там чуть выше функции setup(), где дефайны по клайн, DEBUG_KLINE закомментируй, а DEBUG_VALUES можешь раскомментить, чтобы проверить как формулы правильно или нет работают. Во вкладке K_line.h функция DEBUGPrint можешь добавить переменных своих для отображения. После того как проект будет к завершению, скомпилируй скетч с закомментированными и DEBUG_KLINE иDEBUG_VALUES, чтобы откладка в терминал больше не шла, не мешала работе и лишнюю память и процессорное время не отъедала.
всем привет! яможет кто подскажет про монитор порта ардуино. Столкнулся с тем, что отсечки времени в мониторе не соответствуют временным и интервалам и задержкам ардуино!!! Проверял интервалы общения БК с ЭБУ авто и выявил то, что вместо интервала в 100 мСек- 94, а вместо 60 мСек - 47!!! Причем 60 увеличиваю до 70 - все равно 47!!! Стало интересно, попробовал Blink с delay и без delay , то же самое. Если сделать еще больше - начнет скакать, то 47, то больше 80-ти. Плата Мега, пробовал на 115200 и 9600 - одинаково!
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 - задержки стали скакать.
В общем я уменьшил задержку до 100 мкСек (до 0 не стал уменьшать- боюсь будет нестабильный запрос), теперь запрос = 1 мСек и обработка ответа = 1 мСек!!! Запросы и ответы стабильны! Спасибо, Макс, за подсказку!
привет всем! По многочисленным просьбам трудящихся переделал язык Меню на русский. Увеличил кол-во символов в строке до 14, стали читабельны почти все надписи. Перешел с 3-го размера шрифта на 2-й, так кол-во символов увеличилось в 1,5 раза и стали доступны нормальные названия пунктов Меню на русском, прямо как в оригинале! Но оказалось что мне уже плохо видно 2-й шрифт с расстояния 70-80 см, приходится напрягать зрение и отвлекаться. Так что пришлось отказаться от этого размера. Еще сделал ввод даты, т.к. оказалось что нужно знать дату для некоторых сообщений, например для сообщения для замены резины на зимнюю!))). Но начал подтормаживать энкодер, оказалось что от русификатора tft.cp437. В общем, пришлось пока отказаться от использования русских надписей! Пока допиливаю Меню, хочу еще сделать чтение и сброс ошибок и чтение данных из ответа ЭБУ (на экране БК) для отладки на месте. (просто у меня есть возможность в пунктах меню изменить некоторые интервалы связи с ЭБУ, корректировать для расчета длительность импульсов впрыска, калибровать датчики и тд.)
понимаю сарказм. Это мой первый БК. До конца не представляю что понадобится отображать, насколько стабильно будет работать связь с ЭБУ в разных режимах авто, скачках напряжения и помехах. Пытаюсь предусмотреть возможность настройки некоторых параметров на месте. Да и хочется задействовать обе страницы Меню (12 пунктов), не зря же я мучился чтобы так сделать! Мне нравится как получилось, хотя для уже отлаженного БК можно сделать Меню одностраничное (сгруппировать некоторые пункты).
Вот ведь! Оказывается русский шрифт БК не помеха!!! ))) Всегда интересовало, если на старуху бывает проруха, то что на старика бывает??? ) Буду дальше искать причину глюков энкодера
Всем привет. Забыл сразу написать, причиной глюков энкодера было использование монитора порта. Вобщем при проверке работы энкодера монитор порта лучше отключать! А вообще, проект в очередной раз заброшен, слишком я его усложнил лишними примочками! Есть надежда его упростить и наконец закончить, т.к. пока еще езжу на Нексии! )))
Я имел ввиду попробовать новый код и сделать лог. Модернизировать старый код плохая затея он не оптимален и будет тормозить программу даже без задержки delay (100). Т. К. Он пытается принять все сообщение сразу за один проход луп. А без delay, возможно сообщение будет разрезано на 2 или более и тогда каша. Переделывать с новым кодом то минимум, формулы все те-же вставишь, только с номерами байт принятого сообщения немного подправить возможно придётся.
Макс, у меня в коде нет ни одного прерывания, поэтому изъятие байт из Serial-а прерываться не будет. И чем хорош твой код из 157 сообщения, я извлекаю байты из Serial-а не со скоростью 10400 бод, как он посылает, а с максимальной скоростью процессора(это примерно 50 мкСек на байт). Поэтому чтобы изъять все сообщение мне нужно будет не более 2 мСек! Этого даже энкодер не заметит!!!
ну поступай как знаешь . Тебе предложили более лучший вариант, вставить его в текущий код не проблема. Причина сопротивления непонятна. Тот код корявый , это я тебе как автор говорю. Если не будешь его применять . просто проверь хотябы #2185 как работает, изменив тот список пидов на свой один 2102. и машина какая напиши.
ок, Макс, я попробую. Ты не обижайся, просто я не программист, я электронщик, и мне придется много времени потратить чтобы все собрать в одно по твоему новому варианту. Но я это обязательно сделаю! А пока проверю мою версию, сколько времени уходит на подпрограмму Recieve(). Макет БК собран, можно проводить полноценные эксперименты связи с ЭБУ. Кстати, я попробую твой новый код для начала отдельно, без интеграции в БК, так будет проще. Спасибо за помощь! ))) Машина Нексия N-150, с 16-ти клапанным двигателем и ЭБУ Sirius D42
а че мне обижаться, это было скорее раздражение. я пытался тебе объяснить преимущества нового подхода, а ты мне про нет прерываний и что извлекаются байты из буфера уарт со скоростью процессора. А как быстро эти байты туда попадают? правильно, со скоростью 10400. весь ответ ЭБУ из 38 байт туда попадет примерно через 36 мс. как только первый байт туда попал, начинается работа функции receive() , поэтому задержка 100 мс и нужна чтобы дождаться остальные байты, ну или вариации были без нее , всё равно дожидаясь остальных байт функция работает, а это 36 мс. Не комильфо, я щитаю . То что попробуешь, это правильно. Если заработает, думаю лучше потратить время и перейти на новый вариант.
вот засада! Не могу подключиться к ЭБУ! Новый распаянный макет не подключается, раньше подключался с макетом на штырьках- и все работало! У меня в новом макете даже все детали K-Line адаптера с того макета. Правда раньше была плата Uno, а теперь Mega. на Меге пробовал подключиться и с Serial2 и с SoftSerial (на те же выводы чтобы не перепаивать). Нет инициализации и все тут! Проверил работу адаптера- выдает и 0, и 1 (когда соответствующий сигнал на входе). Пробовал соединение ELM327 через блютуз на телефон-все работает, соединение с ЭБУ в норме! Аж остатки мозга закипели!!! ))) Шился скетчем из 157 поста, который раньше у меня работал и с него делал несколько логов. Вот такие дела!
опа, импульсный ИП на LM2576, вот где похоже собака-то! И К-Лайновский нагрузочный резистор надо уменьшить с 3,3 кОм до 510 Ом!
если что, на всякий скажу, что разница софтсериала и хардсериала есть, в контексте работы с к-линией. При работе через софтсериал отправленные байты НЕ прилетают обратно в приемник (эффекта эхо нет), а при работе через хардсериал прилетают (эффект эхо присутствует). Это надо учитывать в скетче. Не факт что причина у тебя в этом , но чтоб знал. В скетче #2185 есть эта настройка (8 строка) .
Правда раньше была плата Uno, а теперь Mega. на Меге пробовал подключиться и с Serial2 и с SoftSerial (на те же выводы чтобы не перепаивать).
И ещё. На меге 2560 ноги, предназначенные для сериал2 не поддерживают softserial (точнее сказать Rx софт сериал), т. к. на них нет прерывания pcint.
спасибо, Макс! По правде говоря не знал этого. Ну что ж, попробую сериал3 с изначальным скетчем.
ну вот, наконец-то заработала связь с ЭБУ! Спасибо Максу! Заработало на сериале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протестировал на БК, прикольно смотреть как повышается температура двигателя и изменяется напряжение бортовой сети! ))) Теперь нужно все доводить до ума. Кстати, посчитал что интервал опроса в 150 мСек маловат (со всеми интервалами по официальному протоколу) , возможны глюки. Поэтому увеличиваю интервал опроса до 200 мСек. Посмотрим как будут себя вести интервалы загрузки значков, экрана, меню, а главное не будет ли глючить энкодер!
похоже я не дождусь проверки скетча #2185 ...
Макс, я ж писал что не программист, а электронщик. Поэтому пока разберусь в твоем скетче, пока смогу переделать под свои нужды- пройдет еще пол года!
не нужно интегрировать в свой проект, просто залей мой скетч и проверь. Для этого вроде не надо быть программистом.
#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(); // отладка (отправка параметров в терминал) }Ок, попробую
и скинь часть скетча где все формулы , я тебе их запихаю в свой скетч . дело 2х минут. потом в своём проекте удалишь все, что касается клайн . Вставишь в луп функцию k_line() и заинклюдишь файл "K_lineNexia_sirius.h" (я тебе в него упакую свой скетч), я думаю тогда у тебя это не полгода займет, а несколько минут.
спасибо, конечно... Хотя я и половины не понял чего ты написал! ))).Попробовал твой скетч #2215 работает, выкладываю Лог
Макс, разобрался в том, что ты мне написал, только один вопрос: про какие формулы идет речь? Формулы преобразования данных, получаемых через Клайн? и формулы расчета расхода топлива?
Получаемых данных через клайн. Весь скетч выложи да и все.
Макс, у меня в проекте 9 файлов подпрограмм, не считая файлов с логотипом, значками и др. Если я эти 9 файлов просто соберу в один, то получится портянка длиной в 3000 строк! Попробую некоторые подпрограммы убрать или сделать пустыми.
на яндекс диск всё положи и скинь ссылку
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 *************************************************************Сори, не на тот проект ссылка была! вот правильная
https://disk.yandex.ru/d/iUhOyLVEkkjgrQ
проверяй
привет, Макс! Проверил тобой измененный скетч, работает. Выкладываю лог. В нем есть сбои ответов- это я переходил в меню и перебирал в нем пункты.
ну супер. теперь там чуть выше функции setup(), где дефайны по клайн, DEBUG_KLINE закомментируй, а DEBUG_VALUES можешь раскомментить, чтобы проверить как формулы правильно или нет работают. Во вкладке K_line.h функция DEBUGPrint можешь добавить переменных своих для отображения. После того как проект будет к завершению, скомпилируй скетч с закомментированными и DEBUG_KLINE и DEBUG_VALUES, чтобы откладка в терминал больше не шла, не мешала работе и лишнюю память и процессорное время не отъедала.
ок, спасибо, Макс!
всем привет! яможет кто подскажет про монитор порта ардуино. Столкнулся с тем, что отсечки времени в мониторе не соответствуют временным и интервалам и задержкам ардуино!!! Проверял интервалы общения БК с ЭБУ авто и выявил то, что вместо интервала в 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 - задержки стали скакать.
это логи Blink-ов
вставь свой таймштамп на миллис , а идэшный убери в настройках
ну вот, исчезли 7 моих сообщений
В общем я уменьшил задержку до 100 мкСек (до 0 не стал уменьшать- боюсь будет нестабильный запрос), теперь запрос = 1 мСек и обработка ответа = 1 мСек!!! Запросы и ответы стабильны! Спасибо, Макс, за подсказку!
привет всем! По многочисленным просьбам трудящихся переделал язык Меню на русский. Увеличил кол-во символов в строке до 14, стали читабельны почти все надписи. Перешел с 3-го размера шрифта на 2-й, так кол-во символов увеличилось в 1,5 раза и стали доступны нормальные названия пунктов Меню на русском, прямо как в оригинале! Но оказалось что мне уже плохо видно 2-й шрифт с расстояния 70-80 см, приходится напрягать зрение и отвлекаться. Так что пришлось отказаться от этого размера. Еще сделал ввод даты, т.к. оказалось что нужно знать дату для некоторых сообщений, например для сообщения для замены резины на зимнюю!))). Но начал подтормаживать энкодер, оказалось что от русификатора tft.cp437. В общем, пришлось пока отказаться от использования русских надписей! Пока допиливаю Меню, хочу еще сделать чтение и сброс ошибок и чтение данных из ответа ЭБУ (на экране БК) для отладки на месте. (просто у меня есть возможность в пунктах меню изменить некоторые интервалы связи с ЭБУ, корректировать для расчета длительность импульсов впрыска, калибровать датчики и тд.)
Вы пассажиром в авто передвигаетесь ?
понимаю сарказм. Это мой первый БК. До конца не представляю что понадобится отображать, насколько стабильно будет работать связь с ЭБУ в разных режимах авто, скачках напряжения и помехах. Пытаюсь предусмотреть возможность настройки некоторых параметров на месте. Да и хочется задействовать обе страницы Меню (12 пунктов), не зря же я мучился чтобы так сделать! Мне нравится как получилось, хотя для уже отлаженного БК можно сделать Меню одностраничное (сгруппировать некоторые пункты).
Вот ведь! Оказывается русский шрифт БК не помеха!!! ))) Всегда интересовало, если на старуху бывает проруха, то что на старика бывает??? ) Буду дальше искать причину глюков энкодера
Всем привет. Забыл сразу написать, причиной глюков энкодера было использование монитора порта. Вобщем при проверке работы энкодера монитор порта лучше отключать! А вообще, проект в очередной раз заброшен, слишком я его усложнил лишними примочками! Есть надежда его упростить и наконец закончить, т.к. пока еще езжу на Нексии! )))