MaksVV такое дело. У меня начал выпендриватся тач, по пречине что изначально китайцы не поставили шлейф, я поставил, но суть не в этом. Хочу заменить другой экран, но.... проблема, что такие экраны как у меня был ( с широкой шиной пинов под мегу + гребенки по бокам, ниже фото) уже не суцествует в природе, есть только совместимы с мегой (которые имеют гребенку пинов по бокам, ниже фото). Купил такой, он не работает с UTFT и UTFTTouch библой, пытался в библах прописать пины тача и экрана, результат белый экран, а работает с скачать MCUFRIEND_kbv и скачать Adafruit-TouchScreen и эта библа понадобится скачать Adafruit GFX graphics , так как экран выдает ид ID=0x1581 то там вроде чип R61581. Думал отделатся малой кровью, но...., там фунции и имена отличаются. Я взял с этой библы пробу тача и вывод текста на экра и скрестил их, получил текст на экране и корды тача выдаваемые в порту. В библе mcufriend_kbv есть пример GLUE_Demo_480x320, там функции и имена как в UTFT, но он не работает. Чувствую еще тот гемор будет со скетчем. Задача переделать скетч под эти библы и не потерять функционал скетча. Я пробовал некоторые вещи типа замены myGLCD.print на tft.printно там функции отличаются вот и вываливается куча ошибок в компиляции. Я выложу вечером скетчи. Глянь как это можно реализовать, буду очень признателен.
P.S. Если решим эту проблему, выложу и под такие экраны, так как все смогут купить под мегу только совместимы, как купил я.
Был с такими пинами
купил с таким пинами
Нашел уже кое-что. в библе MCUFRIEND_kbv есть некий файл UTFTGLUE.h, он работает как переводчик между UTFT и Adafruit. В скетче по идеи ничего менять не нужно, НО ЕЩЕ НЕ ПРОБОВАЛ, завтра попробую. Если запустится останится разобратся с тачем, я заносил все параметры в скетч для подключения TouccScreen библы до тех пор, пока скетч не начал выдавать ошибки. вод скетч который подправил:
IDE 1.8.9 испльзую
/////////////////////////////////////////////////////////////////////////////////////////
//библиотеки
///////////////////////////////////////////////////////////////////////////////////////////
#include <UTouch.h>
//#include <UTFT.h>
#include <UTFTGLUE.h>//use GLUE class and constructor
#include "TouchScreen.h"
#include <stdint.h>
#include <SPI.h>
#include <EEPROM.h>
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
//датчик наружней температуры
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire);
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
///////////////////////////////////////////////////////////////////////////////////
//пины экрана и тача
///////////////////////////////////////////////////////////////////////////////////
#define YP A1 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 6 // can be a digital pin
#define XP 7 // can be a digital pin
UTFTGLUE myGLCD(0x1581,A2,A1,A3,A4,A0); //all dummy args
//UTFT myGLCD(31,38,39,40,41);
UTouch myTouch(6,5,4,3,2);
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
//#define TFTWIDTH 320
//#define TFTHEIGHT 480
#define MINPRESSURE 10
#define MAXPRESSURE 1000
extern uint8_t GroteskBold16x32[];
int x, y;
char currentPage;
float h;
float t;
bool Dvoet = 0;
//////////////////////////////////////////////////////////////////////////////
//все что касается OBD2
///////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
#define mySerial_gauge Serial2
#define TX_gauge 16
#define TX 13
SoftwareSerial mySerial (12, 13); //RХ,TХ
int length5 = 5;
int length6 = 6;
int length8 = 8;
int length7 = 7;
bool Init = 0;
bool InitGauge = 0;
bool dataMessageOK=0;
bool dataMessageEND = 0;
bool MessageParse = 0;
bool byte0 = 0;
bool byte1 = 0;
bool byte2 = 0;
int numberbyte = 0;
int PIDTime = 120; // задержка ожидания запроса следующего pid 2101, мс
int PresTime = 8000; // задержка между посылками запросов присутствия, мс
int waitbyte = 1; // задержка между отправкой байт в сообщении, мс
int waitbyte_gauge = 4;
int Datadelay = 50; // задержка между отрисовкой данных на LCD, мс
float L100M = 0; //расход на 100 км измеренный за поездку
float L100 = 0; //мгновенный расход литров на 100км
float LHor = 0; //мгновенный расход топлива литров в час
float L100SR = 0; //расход литров на 100км измеренный раз в интервал kmL
float L100SR_TFT = 0; // самый средний из расходов на 100км, он выводится на экран
int L100_Eeprom[11]= {10,10,10,10,10,10,10,10,10,10,10};
int FuelZamer[10]= {0}; // массив для измерения уровня (количества) топлива
int ZamerNumber = 0; // номер замера уровня (количества) топлива
int n_eeprom = 0; // текущий адрес ячейки еепром для записи расхода
int MAF = 0; //26,27 байты Sensor de flujo de aire en masa
float BoostPres = 0; //28,29 байты Presión de refuerzo
int RPM = 0; //32,33 байты Velocidad del motor
int EGRmg = 0; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
float BoostPresCom = 0; //38,39 байты Comando de presión de refuerzo
int Speed = 0; //44,45 байты Velocidad del vehículo
float DesaInjQua = 0; //50,51 байты Cantidad de inyección deseada
float InjQua = 0; //52,53 байты Cantidad de la inyección
float StaDaliv = 0; //54,55 байты Inicio de la entrega
int PumpRPM = 0; //56,57 байты Velocidad de la bomba
float EGRPul = 0; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
float SolenPul = 0; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
float SolenPre = 0; //70,71 байты Relación de impulsos Presión Electroválvula de presión
float DesInj = 0; //72,73 байты Inyección deseada Inicio
float ActInj = 0; //16,17 байты Inicio de la inyección real
int TempAir = 0; //74,75 байты Temperatura del aire de admisión
int Temp = 0; //14,15 байты Temperatura del refrigerante
int TempOil = 0; //18,19 байты Temperatura del aceite del motor
int TempFuel = 0; //58,59 байты Temperatura del combustible
//все что касается топлива
float Fuel = 0; //остаток топлива
float Fuel2 = 0; //остаток мгновенного топлива байт 16 , датчика в баке
int FuelIGN = 0; // количество топлвива в баке на момент включения зажигания
int Fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
float FuelTrip = 0; // количество литров топлива, израсходованное за один цикл включения зажигания
//все что касается километража
float kmAge = 0; //пробег, полученный со щитка приборов
int kmAgeIGN = 0; //пробег который был в момент включения зажигания
int kmAge_last = 0; // для формул
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
float kmTrip = 0; //пробег за один цикл включения зажигания
int kmL = 10; // интервал, через который будет происходить обновление среднего расхода на 100км
int km = 0; // переменная для расчетов
int kmeeprom = 10; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING = 0; // пробег до заправки на остатке топлива
int colerror = 0; //количество ошибок в правом верхнем углу третьего экрана
//float Barom = 0; // барометр
byte MessageRx[110] = {0}; // массив байтов принимаемого сообщения
byte MessageRxGauge[60] = {0}; // массив байтов принимаемого сообщения от щитка приборов
byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04}; // запрос инициализации
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1}; // запрос присутствия
byte messagePids[6] = {0x82,0x11,0xF1,0x21,0x01,0xA6}; // запрос пид 2101
byte messageREAD[8] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
byte messageERASE[7] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98}; // стирание ошибок
unsigned long prevPID = 0;
unsigned long prevPIDgauge = 0;
unsigned long prevTemperature = 0;
unsigned long prevpres = 0;
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
unsigned long prevData = 0;
unsigned long TimewaitPID, timerwaitPID = 0;
bool timerenabledPID = 0;
#define TIMEREXPIRED_PID (TimewaitPID - timerwaitPID)> 200 // здесь задержка на ожидание правильного ответа пидов, мс
unsigned long TimewaitInit, timerwaitInit = 0;
bool timerenabledInit = 0;
#define TIMEREXPIRED_Init (TimewaitInit - timerwaitInit)> 500 // здесь задержка на ожидание ответа об удачной инициализации, мс
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint16_t ID;
void setup() {
myGLCD.setRotation(2);
ID = myGLCD.readID();
if (ID == 0x1581) ID = 0x1581;
myGLCD.begin(ID);
Serial.begin(115200);
mySerial.begin(10400);
Wire.begin();
rtc.begin();
dht.begin();
sensors.begin();
myGLCD.InitLCD(3);
myGLCD.clrScr();
myTouch.InitTouch();
myTouch.setPrecision(PREC_MEDIUM);
myGLCD.setFont(GroteskBold16x32);
//загрузка стартовой страницы
currentPage = '0';
drawHomeScreen();
//подсчет среднеарифметического усредненного расхода
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.0;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить времая и дату, залить в ардуино. в скетче закоментировать
// обратно и залить еще раз, иначе каждый раз будет по новой выствлятся это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2017, 7, 21, 13, 57, 0));
Temperature ();
pinMode(TX, OUTPUT);
pinMode(TX_gauge, OUTPUT);
fastinit();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP FIN
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LOOP
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
TimewaitPID = millis ();
TimewaitInit = millis ();
if (!Init) { if (!timerenabledInit){ timerwaitInit=TimewaitInit; timerenabledInit=1; initialization(); }
else if (TIMEREXPIRED_Init) timerenabledInit=0;}
else { if (currentPage != '3'){ // если открыта страница 0,1 или 2 шлем запрос пид2101, если страница 3 - шлем запрос присутствия
if (millis() - prevPID > PIDTime) { PIDs(); prevPID = millis(); }}
else if (millis() - prevpres > PresTime) {present(); prevpres = millis();}}
if (!InitGauge) {Serial.println ("Otpravil zapros adress Gauge");
digitalWrite (TX_gauge, HIGH); delay (500);
digitalWrite (TX_gauge, LOW); delay (20);
digitalWrite (TX_gauge, HIGH ); delay (15);
digitalWrite (TX_gauge, LOW); delay (5);
digitalWrite (TX_gauge, HIGH); delay (5);
mySerial_gauge.begin(9600);}
receive ();
if (millis() - prevWatch > 3000) { Watch (); prevWatch = millis(); Trip ();}
if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();}
if (millis() - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 285, 0);} else {myGLCD.print(" ", 285, 0);} prevDvoet = millis(); Dvoet=!Dvoet;}
Menu();
LCDDataPrint();}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//BOID TRIP//////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void Trip () {
if (flagkmAgeIGN){
FuelTrip = FuelIGN - Fuel;
if (kmAge>kmAgeIGN) kmTrip = kmAge - kmAgeIGN;
if (kmAge<kmAgeIGN) kmTrip = 2000 - (kmAgeIGN - kmAge); // 2000 это через сколько км у тебя суточный пробег сбрасывается на ноль, поменяй если другое число
if (kmAge==kmAgeIGN) kmTrip = 0;
//подсчет расхода на 100км за поездку
L100M = ((float)FuelTrip*100.00)/(float)kmTrip;
if (L100M<0) L100M = 0;
if (L100M>99) L100M = 99;
// ниже цикл считает среднеарифметический расход из еепром раз в пробег, указанный в переменной kmeeprom
if (kmTrip-kmTFT>kmeeprom) {kmTFT = kmTrip;
// тут считаем среднеарифметический усредненного расход из ячеек еепром
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;}
// ниже цикл считает расход топлива за пробег, указанный в переменной kmL, здесь же запись в ячейки еепром
if (kmTrip-km>kmL) {km=kmTrip;
L100SR = ((float)(Fuel_last-Fuel)*100.00)/(float)kmL; // расход/100км - обновляется раз в 10км, меняется км в int kmL = 10;
Fuel_last = Fuel; // сохранение параметров с последнего измерениея
if (L100SR<0) L100SR = 0;
if (L100SR>99) L100SR = 99;
//расчет остатка километров в баке
if (L100SR>0) kmREFUELING=((float)Fuel*100.0)/(float)L100SR; //если средний расход больше нуля, то расчитывать км в баке из него
else kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT; //если ноль или ментше то расчитывать км в баке с устредненного расхода
// тут записываем L100SR последовательно в одну из 11 ячеек еепром
//EEPROM.write (12,n_eeprom); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
n_eeprom = EEPROM.read (12); // в ячейке 12 хранится № текущей ячейки для записи расхода, чтобы где остановился при выкл питания, от туда и продолжил
EEPROM.write(n_eeprom, L100SR*10);
n_eeprom++; if (n_eeprom>10) n_eeprom=0;
EEPROM.write (12,n_eeprom); }}}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//BOID LCDDATAPRINT. прописываем данные и их расположение и цвет/////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void LCDDataPrint(){
unsigned long curData = millis();
if (millis() - prevData > Datadelay){
myGLCD.setColor(255, 255, 255); //цвет текста
myGLCD.printNumI(Speed, 350, 0, 3);
//----------------------------------------------------------
//страниц HOME
//----------------------------------------------------------
if (currentPage == '0') {
myGLCD.printNumF(LHor, 1, 60, 40, '.',5);
myGLCD.printNumF(L100, 1, 210, 40,'.',5 );
myGLCD.printNumF(L100M, 1, 60, 75,'.',5 );
myGLCD.printNumF(L100SR_TFT, 1, 210, 75,'.',5 );
myGLCD.printNumI(kmREFUELING, 60, 110,5 );
//if (Fuel<53)
myGLCD.printNumF(Fuel, 1, 210, 110,'.',5);
//else myGLCD.print("MAX", 210, 110);
myGLCD.printNumF(kmTrip, 1, 60, 145,'.',5);
myGLCD.printNumF(FuelTrip, 1, 210, 145,'.',5);
myGLCD.printNumI(PumpRPM, 210, 180,5);
myGLCD.printNumI(RPM, 210, 215,5);
myGLCD.printNumF(Fuel2, 1, 0, 215,'.',5);
myGLCD.printNumI(Temp, 415, 40, 3);
myGLCD.printNumI(TempOil, 415, 75, 3);
myGLCD.printNumI(TempFuel, 415, 110,3);
myGLCD.printNumI(sensors.getTempCByIndex(0), 415, 145 , 3);
myGLCD.printNumI(t, 415, 180, 3);
myGLCD.printNumI(TempAir, 415, 215, 3); }
//----------------------------------------------------------
//страниц INF1
//----------------------------------------------------------
if (currentPage == '1') {
myGLCD.printNumF(StaDaliv,1, 395, 40,'.', 3);
myGLCD.printNumF(DesInj,1, 395, 75, '.', 4);
myGLCD.printNumF(ActInj,1, 395, 110,'.', 4);
myGLCD.printNumF(DesaInjQua,1, 395, 145,'.', 4);
myGLCD.printNumF(InjQua,1, 395, 180,'.', 4);
myGLCD.printNumI(MAF, 170, 215, 4);
myGLCD.printNumF(h, 1, 415, 215); }
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
myGLCD.printNumF(BoostPres,1, 395, 40,'.', 4);
myGLCD.printNumF(BoostPresCom,1, 395, 75,'.', 4);
myGLCD.printNumI(EGRmg, 395, 110, 4);
myGLCD.printNumF(EGRPul,1, 395, 145,'.',3);
myGLCD.printNumF(SolenPul, 1, 395, 180,'.', 4);
myGLCD.printNumF(SolenPre, 0, 395, 215,'.', 3); }
prevData = millis(); }}
///////////////////////////////////////////////////////////////////////////
//BOID PIDs//отправка запроса пид 2101/////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void PIDs() {
Serial.println ("Otpravil zapros 21 01");
for (int i = 0; i < length6; i++) {
mySerial.write(messagePids[i]);
delay (waitbyte); }}
///////////////////////////////////////////////////////////////////////////
//BOID PIDsGAUGR//отправка запроса на панель приборов//////////////////////
///////////////////////////////////////////////////////////////////////////
void PIDsGauge() {
Serial.println (" Otpravil zapros 02 11 na panel");
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write(byte(0)); delay (1);
mySerial_gauge.write (0x13); }
///////////////////////////////////////////////////////////////////////////
//BOID PIDsGAUGR//отправка запроса присутствия/////////////////////////////
///////////////////////////////////////////////////////////////////////////
void present() {
Serial.println ("Otpravil zapros Present");
for (int i = 0; i < length5; i++) {
mySerial.write(messagePresent[i]);
delay (waitbyte); }}
/////////////////////////////////////////////////////////////////////////////////////////////
//получение данных от ЭБУ, разборка входящих сообщений
/////////////////////////////////////////////////////////////////////////////////////////////
void receive () {
///////////////////////////////////////////////////////////////////////
////////////////// работа с К-Line софт сериал 16-17 (12 контакт ОБД)
///////////////////////////////////////////////////////////////////////
while(!InitGauge){
if (mySerial_gauge.available()) {
byte inByte = mySerial_gauge.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {mySerial_gauge.write (0x7F); delay (1);}
if (inByte==0xF0) {
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write (0x00); delay (1);
mySerial_gauge.write (0x13); delay (1); InitGauge=1; }}}
MessageParse = 0;
while (InitGauge && !MessageParse) {
if (!dataMessageOK) {
if (mySerial_gauge.read() == 0x23) {byte0=1; delay (waitbyte_gauge); }
if (mySerial_gauge.read() == 0xA1 && byte0) {byte1=1; delay (waitbyte_gauge);}
else byte0=0;
if (mySerial_gauge.read() == 0x04 && byte0 && byte1) {byte2=1; delay (waitbyte_gauge);}
else {byte0=0; byte1=0;}
if (byte0 && byte1 && byte2) {dataMessageOK = 1; byte0=0; byte1=0; byte2=0;}
numberbyte=0;}
else { if (mySerial_gauge.available()>0) { MessageRxGauge[numberbyte] = mySerial_gauge.read(); numberbyte++; delayMicroseconds (250);}
if (numberbyte==34) {dataMessageEND = 1; dataMessageOK = 0; }}
if (dataMessageEND) {
int crc = ( ( unsigned int )MessageRxGauge[32] << 8 ) | MessageRxGauge[33]; // парсинг контрольной суммы из 2 последних байт
int CRC =200;
for (int i = 0; i < 32; i++) CRC = CRC + MessageRxGauge[i]; // подсчет контрольной суммы байт от 0 до 31
Serial.print (" ReceiveGauge: ");
for (int i = 0; i < 34; i++) {
Serial.print(MessageRxGauge[i],HEX); Serial.print (" ");}
//при получении сообщения БЕЗ ошибок с данными от панели приборов, запишем в переменные остаток топлива и пробег
if (CRC==crc) {Serial.println (" OK!!!");
Fuel2 = MessageRxGauge[16]/2.0;
if (!flagFuelIGN) { Fuel = MessageRxGauge[16]/2.00; kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;} //стартовая запись литров в баке для подсчета затраченных литро
else Fuel = MessageRxGauge[17]/2.0; //для устреднения болтания в баке закоментировать эту строку, а раскоментировать ниже
//для усреднения болтания топлива в баке, раскоментировать, высчитывает среднее
/*else { FuelZamer[ZamerNumber] = MessageRxGauge[17]/2.00;
if (ZamerNumber==9) {
Fuel = 0 ;
for (int i = 0; i < 10; i++) Fuel = Fuel + FuelZamer[i];
Fuel = (float)Fuel/10.0;}
ZamerNumber++; if (ZamerNumber>9) ZamerNumber = 0;}
*/
kmAge = (MessageRxGauge[23]+(MessageRxGauge[24]*256))/10.0; //суточный пробег с панели приборов
//бак у меня на 59 литров, а датчик показывает максимально 53 литра. для этого эта формула
//если у вас тоже датчик имеет лимит то подправте 53 на свой лимит.
//если ваш датчик показывает одинаково с полным баком то закоментировать три нижние строки.
if (Fuel<53){
if (!flagkmAgeIGN) { kmAgeIGN = kmAge; flagkmAgeIGN =1;}
if (!flagFuelIGN) { FuelIGN = Fuel; Fuel_last = Fuel; flagFuelIGN = 1; }}}
else Serial.println (" ERROR!!!");
dataMessageEND = 0; MessageParse = 1; //mySerial_gauge.flush();
for (int i = 0; i < 34; i++) MessageRxGauge[i]=0; }} // очистка байтов массива
////////////////////////////////////////////////////////////////////
////////////////// работа с К-Line софт сериал 12-13 (7 контакт ОБД)
////////////////////////////////////////////////////////////////////
if (mySerial.available()) {
delay(195);
int k=0;
byte inbyte=0;
while( mySerial.available() && k < 110) {
inbyte = mySerial.read();
MessageRx[k] = inbyte;
k++; }
Serial.print ("Receive: ");
for (int i = 0; i < k; i++) {
Serial.print(MessageRx[i],HEX); Serial.print (" ");}
Serial.println ("");
if (MessageRx[2]==0x83 && MessageRx[3]==0xF1 && MessageRx[4]==0x11 && MessageRx[5]==0xC1 && MessageRx[6]==0x6B && MessageRx[7]==0x8F && MessageRx[8]==0x40) {Init=1;
timerenabledInit=0;
Serial.println (" Initialization OK!!!!: "); }
if (currentPage == '3'){
///////////////////////////////////////////////////////////////////////////////////////////////////
//Чтение и стирание ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////
//при получении этого сообщения выдавать на третий экран "NO ERROR"
if (MessageRx[4]==0x82 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]==0x00 && MessageRx[9]==0xDC){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 165, 145);
Serial.println (" NO DTC "); }
//при получении этого сообщения выдавать на третий экран "DTC BORRADO"
if (MessageRx[3]==0x83 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x54 && MessageRx[7]==0xFF && MessageRx[8]==0x00 && MessageRx[9]==0xD8){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 165, 145);
Serial.println (" DTC BORRADO "); }
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]>0){
Serial.println ("DTC is found!");
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx[8]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx[11+(i*3)],6) && bitRead(MessageRx[11+(i*3)],7)){ myGLCD.setColor (0,255,0);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx[11+(i*3)],7) && bitRead(MessageRx[11+(i*3)],6)) {myGLCD.setColor (255,0,0);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx[9+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx[9+(i*3)]<=0x0F&&MessageRx[9+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}
if (nolA)myGLCD.print(String (MessageRx[9+(i*3)],HEX), 246, (75+y));
else myGLCD.print(String (MessageRx[9+(i*3)],HEX), 230, (75+y));
if (MessageRx[10+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx[10+(i*3)]<=0x0F&&MessageRx[10+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;}
if (nolB)myGLCD.print(String (MessageRx[10+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx[10+(i*3)],HEX), 262, (75+y));}}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописываем формулы к данным ///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
else if (MessageRx[3]==0x80 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x4C && MessageRx[7]==0x61 && MessageRx[8]==0x01) {
//Barom = MessageRx[39];
L100 = (float)LHor*100.0/(float)Speed;
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
MAF = ((MessageRx[29]*256)+MessageRx[30])/10;
BoostPres = ((MessageRx[31]*256)+MessageRx[32])/1000.0;
RPM = (MessageRx[35]*256)+MessageRx[36];
EGRmg = ((MessageRx[37]*256)+MessageRx[38])/10.0;
BoostPresCom = ((MessageRx[41]*256)+MessageRx[42])/1000.0;
Speed = ((MessageRx[47]*256)+MessageRx[48])/100;
DesaInjQua = ((MessageRx[53]*256)+MessageRx[54])/100.0;
InjQua = ((MessageRx[55]*256)+MessageRx[56])/100.0;
StaDaliv = ((MessageRx[57]*256)+MessageRx[58])/100.0;
PumpRPM = (MessageRx[59]*256)+MessageRx[60];
EGRPul = ((MessageRx[65]*256)+MessageRx[66])/100.0;
SolenPul = ((MessageRx[67]*256)+MessageRx[68])/100.0;
SolenPre = ((MessageRx[73]*256)+MessageRx[74])/100.0;
DesInj = ((MessageRx[75]*3)+(MessageRx[76])/100.0)+0.3;
ActInj = ((MessageRx[19]*3)+(MessageRx[20])/100.0)+0.3;
//TempAir = ((MessageRx[77]*26)-278)+MessageRx[78]/10.0;
//Temp = ((MessageRx[17]*26)-278)+MessageRx[18]/10.0;
//TempOil = ((MessageRx[21]*26)-278)+MessageRx[22]/10.0;
//TempFuel = ((MessageRx[61]*26)-278)+MessageRx[62]/10.0;
//ниже идут расчетные формулы более точные чем те что закоментированы выше
int A = 0;
if (MessageRx[77]<=0x0A) A = 277;
if (MessageRx[77]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[77]>=0x0D) A = 279;
double B = MessageRx[78]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx[77]*26)-A)+cel;
if (MessageRx[17]<=0x0A) A = 277;
if (MessageRx[17]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[17]>=0x0D) A = 279;
B = MessageRx[18]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx[17]*26)-A)+cel;
if (MessageRx[21]<=0x0A) A = 277;
if (MessageRx[21]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[21]>=0x0D) A = 279;
B = MessageRx[22]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx[21]*26)-A)+cel;
if (MessageRx[61]<=0x0A) A = 277;
if (MessageRx[61]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[61]>=0x0D) A = 279;
B = MessageRx[62]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx[61]*26)-A)+cel;
timerenabledPID=0; }
for (int i = 0; i < 110; i++) MessageRx[i]=0; }} // очистка байтов массива
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//отправка запроса на диагностическое соединение
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initialization() {
Serial.println ("Otpravil zapros Init");
for (int i = 0; i < length5; i++) {
mySerial.write(messageInit[i]);
delay (5); }
delay (55); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//стартовая инициализация 7 пина ОБД
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fastinit() {
digitalWrite (TX, HIGH); // makes K-line high 3
delay(360); // wait for K-line to be clear 3
digitalWrite (TX, LOW); // makes K-line low 3
delay(25);
digitalWrite (TX, HIGH); // makes K-line high 3
delay(25); //last delay before first message
mySerial.begin(10400); } // baud rate of the OBD
///////////////////////////////////////////////////////////////////////////////////////////////////////
//запрос чтения и стирания ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////////
void Read() {
Serial.println ("Zapros error; ");
for (int i = 0; i < length8; i++) {
mySerial.write(messageREAD[i]);
delay (waitbyte); }}
void Erase() {
Serial.println ("Zapros erase; ");
for (int i = 0; i < length7; i++) {
mySerial.write(messageERASE[i]);
delay (waitbyte); }}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка тач кнопок
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Menu () {
if (myTouch.dataAvailable()) {
myTouch.read();
x=myTouch.getX();
y=myTouch.getY();
if (currentPage == '0') {
buttonHomeTouch();
buttonINF1Touch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '1') {
buttonHomeTouch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '2') {
buttonHomeTouch();
buttonINF1Touch();
buttonCHECKTouch(); }
if (currentPage == '3') {
buttonHomeTouch();
buttonREADTouch();
buttonERASETouch(); }}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописывает заголовки и кнопки на страницах
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawHomeScreen() {
line() ;
Watch ();
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.setColor(0, 255, 0); // цвет линии зеленый
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(1,178,295,178); // линия горизонтальная
myGLCD.print("L/H", 10, 40);
myGLCD.print("L/A", 148, 40);
myGLCD.print("L/V", 10, 75);
myGLCD.print("L/M", 148, 75);
myGLCD.print("D/K", 10, 110);
myGLCD.print("D/L", 148, 110);
myGLCD.print("V/K", 10, 145);
myGLCD.print("V/L", 148, 145);
myGLCD.print("PUMP RPM", 82, 180);
myGLCD.print("Engi RPM", 82, 215);
myGLCD.print("D/La", 10, 180);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("Oil C", 300, 75);
myGLCD.print("Fuel C", 300, 110);
myGLCD.print("Inter C", 300, 145);
myGLCD.print("Exter C", 300, 180);
myGLCD.print("IntAirC", 300, 215);
buttonHome() ; //прорисовка кнопок
buttonINF1() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
Watch ();
myGLCD.print("Start of Delivery *CA:", 10, 40);
myGLCD.print("Desir inject Start *CA:", 10, 75);
myGLCD.print("Actua Inject Start *CA:", 10, 110);
myGLCD.print("Desir Inject Quan mg/s:", 10, 145);
myGLCD.print("Actu Inject Quant mg/s:", 10, 180);
myGLCD.print("MAF mg/s:", 10, 215);
myGLCD.print("Humedad %:", 255, 215);
buttonHome() ;
buttonINF2() ;
buttonCHECK() ; }
//-------------------------------------------------
void drawscreen_two() {
line() ;
Watch ();
myGLCD.print("Boost Press Bar:", 10, 40);
myGLCD.print("Boost Press Com Bar:", 10, 75);
myGLCD.print("EGR command mg/s:", 10, 110);
myGLCD.print("EGR Pulse Ratio %:", 10, 145);
myGLCD.print("Solenoide Pulse %:", 10, 180);
myGLCD.print("Solenoide Boost %:", 10, 215);
buttonHome() ;
buttonINF1() ;
buttonCHECK() ; }
//----------------------------------------------------------------------------
void drawscreen_three() {
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
buttonHome();
buttonERASE();
buttonREAD(); }
////////////////////////////////////////////////////////////////////////////////////////////////////////
//координаты тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawFrame(int x1, int y1, int x2, int y2) {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect (x1, y1, x2, y2);
while (myTouch.dataAvailable())
myTouch.read();
myGLCD.setColor(255, 255, 255); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка кнопок и координат тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonHome() {
myGLCD.setColor(0,0,0); // цвет кнопки черный
myGLCD.fillRoundRect (1, 1, 80, 33); // расположение кнопки прямоугольника
myGLCD.setColor(255, 255,255); // цвет текста белый
myGLCD.drawRoundRect (1, 1, 65, 33); // кнопка будет рамкой
myGLCD.print("HOME", 1, 0); }// центровка строки
void buttonHomeTouch(){
if ((x>=1) && (x<=65) &&(y>=1) && (y<=33)) {
drawFrame(1, 1, 65, 33);
currentPage = '0';
myGLCD.clrScr();
drawHomeScreen(); }}
void buttonINF1() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("INF 1", 25, 265); }
void buttonINF1Touch() {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
currentPage = '1';
myGLCD.clrScr();
drawscreen_one(); }}
void buttonINF2() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (180, 255, 300, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (180, 255, 300, 310);
myGLCD.print("INF 2", 200, 265); }
void buttonINF2Touch() {
if ((x>=180) && (x<=300) && (y>=255) && (y<=310)) {
drawFrame(180, 255, 300, 310);
currentPage = '2';
myGLCD.clrScr();
drawscreen_two(); }}
void buttonCHECK() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("CHECK", 375, 265);}
void buttonCHECKTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
currentPage = '3';
myGLCD.clrScr();
drawscreen_three(); }}
void buttonERASE() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("ERASE", 25, 265); }
void buttonERASETouch () {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
Erase(); }}
void buttonREAD() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("READ", 375, 265); }
void buttonREADTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
Read(); }}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,73,479,73); // линия горизонтальная
myGLCD.drawLine(1,108,479,108); // линия горизонтальная
myGLCD.drawLine(1,143,479,143); // линия горизонтальная
myGLCD.drawLine(1,178,479,178); // линия горизонтальная
myGLCD.drawLine(1,212,479,212); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); }// линия горизонтальная
/////////////////////////////////////////////////////////////////////////////////////////////
//верхняя часть экрана часы и дата отображается на всех экранах
/////////////////////////////////////////////////////////////////////////////////////////////
void Watch (){
DateTime now = rtc.now();
int m = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
myGLCD.setColor(0, 255, 0); //зеленый цвет цифры
if (date<10) {
myGLCD.print("0", 85, 0);
myGLCD.printNumI(now.day(), 100, 0); }
else if (date >=10) {
myGLCD.printNumI(now.day(), 85, 0); }
myGLCD.print("/", 115, 0);
if ( mon<10) {
myGLCD.print("0", 130, 0);
myGLCD.printNumI(now.month(), 145, 0);}
else if (mon >=10) {
myGLCD.printNumI(now.month(), 130, 0);}
myGLCD.print("/", 160, 0);
myGLCD.printNumI(now.year(), 175, 0);
if (hour<10) {
myGLCD.print("0",255, 0);
myGLCD.printNumI(now.hour(), 270, 0); }
else if(hour>=10){
myGLCD.printNumI(now.hour(), 255, 0); }
if (m<10) {
myGLCD.print("0",300, 0);
myGLCD.printNumI(now.minute(), 315, 0); }
else if (m>=10){
myGLCD.printNumI(now.minute(), 300, 0); }
myGLCD.print("Km/h", 410, 0); }
void Temperature (){
h = dht.readHumidity();
t = dht.readTemperature();
sensors.requestTemperatures(); }
По идеи нужно будет
39 закоментить, и в 8ми строках где myTouch правильно прописать
заработало но отображение корявое. ща буду капать.
Расходы нормально можно ориентироватся на длинных пробежкаках, на коротких так себе, по этому выставил средний 6.7 литров (много раз проверил и высчитал) и норм на коротких и на дальних.
поборол кривезну. осталось разобратся с шрифтом и тачем. вот скетч без тача
/////////////////////////////////////////////////////////////////////////////////////////
//библиотеки
///////////////////////////////////////////////////////////////////////////////////////////
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
#include <UTFTGLUE.h>//use GLUE class and constructor
#include "TouchScreen.h"
#include <stdint.h>
#include <SPI.h>
#include <EEPROM.h>
MCUFRIEND_kbv tft;
//#include "Fonts/GroteskBold16x32.h"
//Adafruit_GFX_Button buttonHome, buttonINF1, buttonINF2, buttonCHECK, buttonERASE, buttonREAD;
extern uint8_t GroteskBold16x32[];
#define BLACK 0x0000
#define MINPRESSURE 200
#define MAXPRESSURE 1000
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
//датчик наружней температуры
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire);
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
///////////////////////////////////////////////////////////////////////////////////
//пины экрана и тача
///////////////////////////////////////////////////////////////////////////////////
//#define YP A1 // must be an analog pin, use "An" notation!
//#define XM A2 // must be an analog pin, use "An" notation!
//#define YM 6 // can be a digital pin
//#define XP 7 // can be a digital pin
UTFTGLUE myGLCD(0x1581,A2,A1,A3,A4,A0); //all dummy args
//оринтеровка тача под myGLCD.setRotation(3);
const int XP = 6, XM = A2, YP = A1, YM = 7;
const int TS_LEFT = 136, TS_RT = 907, TS_TOP = 139, TS_BOT = 942;
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
int pixel_x, pixel_y; //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
TSPoint p = ts.getPoint();
pinMode(YP, OUTPUT); //restore shared pins
pinMode(XM, OUTPUT);
digitalWrite(YP, HIGH); //because TFT control pins
digitalWrite(XM, HIGH);
bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
if (pressed) {
pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
}
return pressed;
}
int x, y;
char currentPage;
float h;
float t;
bool Dvoet = 0;
//////////////////////////////////////////////////////////////////////////////
//все что касается OBD2
///////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
#define mySerial_gauge Serial2
#define TX_gauge 16
#define TX 13
SoftwareSerial mySerial (12, 13); //RХ,TХ
int length5 = 5;
int length6 = 6;
int length8 = 8;
int length7 = 7;
bool Init = 0;
bool InitGauge = 0;
bool dataMessageOK=0;
bool dataMessageEND = 0;
bool MessageParse = 0;
bool byte0 = 0;
bool byte1 = 0;
bool byte2 = 0;
int numberbyte = 0;
int PIDTime = 120; // задержка ожидания запроса следующего pid 2101, мс
int PresTime = 8000; // задержка между посылками запросов присутствия, мс
int waitbyte = 1; // задержка между отправкой байт в сообщении, мс
int waitbyte_gauge = 4;
int Datadelay = 50; // задержка между отрисовкой данных на LCD, мс
float L100M = 0; //расход на 100 км измеренный за поездку
float L100 = 0; //мгновенный расход литров на 100км
float LHor = 0; //мгновенный расход топлива литров в час
float L100SR = 0; //расход литров на 100км измеренный раз в интервал kmL
float L100SR_TFT = 0; // самый средний из расходов на 100км, он выводится на экран
int L100_Eeprom[11]= {10,10,10,10,10,10,10,10,10,10,10};
int FuelZamer[10]= {0}; // массив для измерения уровня (количества) топлива
int ZamerNumber = 0; // номер замера уровня (количества) топлива
int n_eeprom = 0; // текущий адрес ячейки еепром для записи расхода
int MAF = 0; //26,27 байты Sensor de flujo de aire en masa
float BoostPres = 0; //28,29 байты Presión de refuerzo
int RPM = 0; //32,33 байты Velocidad del motor
int EGRmg = 0; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
float BoostPresCom = 0; //38,39 байты Comando de presión de refuerzo
int Speed = 0; //44,45 байты Velocidad del vehículo
float DesaInjQua = 0; //50,51 байты Cantidad de inyección deseada
float InjQua = 0; //52,53 байты Cantidad de la inyección
float StaDaliv = 0; //54,55 байты Inicio de la entrega
int PumpRPM = 0; //56,57 байты Velocidad de la bomba
float EGRPul = 0; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
float SolenPul = 0; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
float SolenPre = 0; //70,71 байты Relación de impulsos Presión Electroválvula de presión
float DesInj = 0; //72,73 байты Inyección deseada Inicio
float ActInj = 0; //16,17 байты Inicio de la inyección real
int TempAir = 0; //74,75 байты Temperatura del aire de admisión
int Temp = 0; //14,15 байты Temperatura del refrigerante
int TempOil = 0; //18,19 байты Temperatura del aceite del motor
int TempFuel = 0; //58,59 байты Temperatura del combustible
//все что касается топлива
float Fuel = 0; //остаток топлива
float Fuel2 = 0; //остаток мгновенного топлива байт 16 , датчика в баке
int FuelIGN = 0; // количество топлвива в баке на момент включения зажигания
int Fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
float FuelTrip = 0; // количество литров топлива, израсходованное за один цикл включения зажигания
//все что касается километража
float kmAge = 0; //пробег, полученный со щитка приборов
int kmAgeIGN = 0; //пробег который был в момент включения зажигания
int kmAge_last = 0; // для формул
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
float kmTrip = 0; //пробег за один цикл включения зажигания
int kmL = 10; // интервал, через который будет происходить обновление среднего расхода на 100км
int km = 0; // переменная для расчетов
int kmeeprom = 10; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING = 0; // пробег до заправки на остатке топлива
int colerror = 0; //количество ошибок в правом верхнем углу третьего экрана
//float Barom = 0; // барометр
byte MessageRx[110] = {0}; // массив байтов принимаемого сообщения
byte MessageRxGauge[60] = {0}; // массив байтов принимаемого сообщения от щитка приборов
byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04}; // запрос инициализации
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1}; // запрос присутствия
byte messagePids[6] = {0x82,0x11,0xF1,0x21,0x01,0xA6}; // запрос пид 2101
byte messageREAD[8] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
byte messageERASE[7] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98}; // стирание ошибок
unsigned long prevPID = 0;
unsigned long prevPIDgauge = 0;
unsigned long prevTemperature = 0;
unsigned long prevpres = 0;
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
unsigned long prevData = 0;
unsigned long TimewaitPID, timerwaitPID = 0;
bool timerenabledPID = 0;
#define TIMEREXPIRED_PID (TimewaitPID - timerwaitPID)> 200 // здесь задержка на ожидание правильного ответа пидов, мс
unsigned long TimewaitInit, timerwaitInit = 0;
bool timerenabledInit = 0;
#define TIMEREXPIRED_Init (TimewaitInit - timerwaitInit)> 500 // здесь задержка на ожидание ответа об удачной инициализации, мс
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint16_t ID;
void setup() {
ID = myGLCD.readID();
if (ID == 0x1581) ID = 0x1581;
myGLCD.begin(ID);
Serial.begin(115200);
mySerial.begin(10400);
Wire.begin();
rtc.begin();
dht.begin();
sensors.begin();
myGLCD.InitLCD(3);
myGLCD.clrScr();
//myGLCD.setFont(GroteskBold16x32);
//buttonINF1.initButton(&myGLCD, 10, 255, 130, 310, WHITE, CYAN, BLACK, "INF1", 2);
//загрузка стартовой страницы
currentPage = '0';
drawHomeScreen();
//подсчет среднеарифметического усредненного расхода
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.0;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить времая и дату, залить в ардуино. в скетче закоментировать
// обратно и залить еще раз, иначе каждый раз будет по новой выствлятся это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2017, 7, 21, 13, 57, 0));
Temperature ();
pinMode(TX, OUTPUT);
pinMode(TX_gauge, OUTPUT);
fastinit();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP FIN
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LOOP
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
TimewaitPID = millis ();
TimewaitInit = millis ();
if (!Init) { if (!timerenabledInit){ timerwaitInit=TimewaitInit; timerenabledInit=1; initialization(); }
else if (TIMEREXPIRED_Init) timerenabledInit=0;}
else { if (currentPage != '3'){ // если открыта страница 0,1 или 2 шлем запрос пид2101, если страница 3 - шлем запрос присутствия
if (millis() - prevPID > PIDTime) { PIDs(); prevPID = millis(); }}
else if (millis() - prevpres > PresTime) {present(); prevpres = millis();}}
if (!InitGauge) {Serial.println ("Otpravil zapros adress Gauge");
digitalWrite (TX_gauge, HIGH); delay (500);
digitalWrite (TX_gauge, LOW); delay (20);
digitalWrite (TX_gauge, HIGH ); delay (15);
digitalWrite (TX_gauge, LOW); delay (5);
digitalWrite (TX_gauge, HIGH); delay (5);
mySerial_gauge.begin(9600);}
receive ();
if (millis() - prevWatch > 3000) { Watch (); prevWatch = millis(); Trip ();}
if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();}
if (millis() - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 285, 0);} else {myGLCD.print(" ", 285, 0);} prevDvoet = millis(); Dvoet=!Dvoet;}
//Menu();
LCDDataPrint();}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//BOID TRIP//////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void Trip () {
if (flagkmAgeIGN){
FuelTrip = FuelIGN - Fuel;
if (kmAge>kmAgeIGN) kmTrip = kmAge - kmAgeIGN;
if (kmAge<kmAgeIGN) kmTrip = 2000 - (kmAgeIGN - kmAge); // 2000 это через сколько км у тебя суточный пробег сбрасывается на ноль, поменяй если другое число
if (kmAge==kmAgeIGN) kmTrip = 0;
//подсчет расхода на 100км за поездку
L100M = ((float)FuelTrip*100.00)/(float)kmTrip;
if (L100M<0) L100M = 0;
if (L100M>99) L100M = 99;
// ниже цикл считает среднеарифметический расход из еепром раз в пробег, указанный в переменной kmeeprom
if (kmTrip-kmTFT>kmeeprom) {kmTFT = kmTrip;
// тут считаем среднеарифметический усредненного расход из ячеек еепром
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;}
// ниже цикл считает расход топлива за пробег, указанный в переменной kmL, здесь же запись в ячейки еепром
if (kmTrip-km>kmL) {km=kmTrip;
L100SR = ((float)(Fuel_last-Fuel)*100.00)/(float)kmL; // расход/100км - обновляется раз в 10км, меняется км в int kmL = 10;
Fuel_last = Fuel; // сохранение параметров с последнего измерениея
if (L100SR<0) L100SR = 0;
if (L100SR>99) L100SR = 99;
//расчет остатка километров в баке
if (L100SR>0) kmREFUELING=((float)Fuel*100.0)/(float)L100SR; //если средний расход больше нуля, то расчитывать км в баке из него
else kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT; //если ноль или ментше то расчитывать км в баке с устредненного расхода
// тут записываем L100SR последовательно в одну из 11 ячеек еепром
//EEPROM.write (12,n_eeprom); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
n_eeprom = EEPROM.read (12); // в ячейке 12 хранится № текущей ячейки для записи расхода, чтобы где остановился при выкл питания, от туда и продолжил
EEPROM.write(n_eeprom, L100SR*10);
n_eeprom++; if (n_eeprom>10) n_eeprom=0;
EEPROM.write (12,n_eeprom); }}}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//BOID LCDDATAPRINT. прописываем данные и их расположение и цвет/////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void LCDDataPrint(){
unsigned long curData = millis();
if (millis() - prevData > Datadelay){
myGLCD.setColor(255, 255, 255); //цвет текста
myGLCD.printNumI(Speed, 350, 0, 3);
//----------------------------------------------------------
//страниц HOME
//----------------------------------------------------------
if (currentPage == '0') {
myGLCD.printNumF(LHor, 1, 60, 40, '.',5);
myGLCD.printNumF(L100, 1, 210, 40,'.',5 );
myGLCD.printNumF(L100M, 1, 60, 75,'.',5 );
myGLCD.printNumF(L100SR_TFT, 1, 210, 75,'.',5 );
myGLCD.printNumI(kmREFUELING, 60, 110,5 );
//if (Fuel<53)
myGLCD.printNumF(Fuel, 1, 210, 110,'.',5);
//else myGLCD.print("MAX", 210, 110);
myGLCD.printNumF(kmTrip, 1, 60, 145,'.',5);
myGLCD.printNumF(FuelTrip, 1, 210, 145,'.',5);
myGLCD.printNumI(PumpRPM, 210, 180,5);
myGLCD.printNumI(RPM, 210, 215,5);
myGLCD.printNumF(Fuel2, 1, 0, 215,'.',5);
myGLCD.printNumI(Temp, 415, 40, 3);
myGLCD.printNumI(TempOil, 415, 75, 3);
myGLCD.printNumI(TempFuel, 415, 110,3);
myGLCD.printNumI(sensors.getTempCByIndex(0), 415, 145 , 3);
myGLCD.printNumI(t, 415, 180, 3);
myGLCD.printNumI(TempAir, 415, 215, 3); }
//----------------------------------------------------------
//страниц INF1
//----------------------------------------------------------
if (currentPage == '1') {
myGLCD.printNumF(StaDaliv,1, 395, 40,'.', 3);
myGLCD.printNumF(DesInj,1, 395, 75, '.', 4);
myGLCD.printNumF(ActInj,1, 395, 110,'.', 4);
myGLCD.printNumF(DesaInjQua,1, 395, 145,'.', 4);
myGLCD.printNumF(InjQua,1, 395, 180,'.', 4);
myGLCD.printNumI(MAF, 170, 215, 4);
myGLCD.printNumF(h, 1, 415, 215); }
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
myGLCD.printNumF(BoostPres,1, 395, 40,'.', 4);
myGLCD.printNumF(BoostPresCom,1, 395, 75,'.', 4);
myGLCD.printNumI(EGRmg, 395, 110, 4);
myGLCD.printNumF(EGRPul,1, 395, 145,'.',3);
myGLCD.printNumF(SolenPul, 1, 395, 180,'.', 4);
myGLCD.printNumF(SolenPre, 0, 395, 215,'.', 3); }
prevData = millis(); }}
///////////////////////////////////////////////////////////////////////////
//BOID PIDs//отправка запроса пид 2101/////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void PIDs() {
Serial.println ("Otpravil zapros 21 01");
for (int i = 0; i < length6; i++) {
mySerial.write(messagePids[i]);
delay (waitbyte); }}
///////////////////////////////////////////////////////////////////////////
//BOID PIDsGAUGR//отправка запроса на панель приборов//////////////////////
///////////////////////////////////////////////////////////////////////////
void PIDsGauge() {
Serial.println (" Otpravil zapros 02 11 na panel");
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write(byte(0)); delay (1);
mySerial_gauge.write (0x13); }
///////////////////////////////////////////////////////////////////////////
//BOID PIDsGAUGR//отправка запроса присутствия/////////////////////////////
///////////////////////////////////////////////////////////////////////////
void present() {
Serial.println ("Otpravil zapros Present");
for (int i = 0; i < length5; i++) {
mySerial.write(messagePresent[i]);
delay (waitbyte); }}
/////////////////////////////////////////////////////////////////////////////////////////////
//получение данных от ЭБУ, разборка входящих сообщений
/////////////////////////////////////////////////////////////////////////////////////////////
void receive () {
///////////////////////////////////////////////////////////////////////
////////////////// работа с К-Line софт сериал 16-17 (12 контакт ОБД)
///////////////////////////////////////////////////////////////////////
while(!InitGauge){
if (mySerial_gauge.available()) {
byte inByte = mySerial_gauge.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {mySerial_gauge.write (0x7F); delay (1);}
if (inByte==0xF0) {
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write (0x00); delay (1);
mySerial_gauge.write (0x13); delay (1); InitGauge=1; }}}
MessageParse = 0;
while (InitGauge && !MessageParse) {
if (!dataMessageOK) {
if (mySerial_gauge.read() == 0x23) {byte0=1; delay (waitbyte_gauge); }
if (mySerial_gauge.read() == 0xA1 && byte0) {byte1=1; delay (waitbyte_gauge);}
else byte0=0;
if (mySerial_gauge.read() == 0x04 && byte0 && byte1) {byte2=1; delay (waitbyte_gauge);}
else {byte0=0; byte1=0;}
if (byte0 && byte1 && byte2) {dataMessageOK = 1; byte0=0; byte1=0; byte2=0;}
numberbyte=0;}
else { if (mySerial_gauge.available()>0) { MessageRxGauge[numberbyte] = mySerial_gauge.read(); numberbyte++; delayMicroseconds (250);}
if (numberbyte==34) {dataMessageEND = 1; dataMessageOK = 0; }}
if (dataMessageEND) {
int crc = ( ( unsigned int )MessageRxGauge[32] << 8 ) | MessageRxGauge[33]; // парсинг контрольной суммы из 2 последних байт
int CRC =200;
for (int i = 0; i < 32; i++) CRC = CRC + MessageRxGauge[i]; // подсчет контрольной суммы байт от 0 до 31
Serial.print (" ReceiveGauge: ");
for (int i = 0; i < 34; i++) {
Serial.print(MessageRxGauge[i],HEX); Serial.print (" ");}
//при получении сообщения БЕЗ ошибок с данными от панели приборов, запишем в переменные остаток топлива и пробег
if (CRC==crc) {Serial.println (" OK!!!");
Fuel2 = MessageRxGauge[16]/2.0;
if (!flagFuelIGN) { Fuel = MessageRxGauge[16]/2.00; kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;} //стартовая запись литров в баке для подсчета затраченных литро
else Fuel = MessageRxGauge[17]/2.0; //для устреднения болтания в баке закоментировать эту строку, а раскоментировать ниже
//для усреднения болтания топлива в баке, раскоментировать, высчитывает среднее
/*else { FuelZamer[ZamerNumber] = MessageRxGauge[17]/2.00;
if (ZamerNumber==9) {
Fuel = 0 ;
for (int i = 0; i < 10; i++) Fuel = Fuel + FuelZamer[i];
Fuel = (float)Fuel/10.0;}
ZamerNumber++; if (ZamerNumber>9) ZamerNumber = 0;}
*/
kmAge = (MessageRxGauge[23]+(MessageRxGauge[24]*256))/10.0; //суточный пробег с панели приборов
//бак у меня на 59 литров, а датчик показывает максимально 53 литра. для этого эта формула
//если у вас тоже датчик имеет лимит то подправте 53 на свой лимит.
//если ваш датчик показывает одинаково с полным баком то закоментировать три нижние строки.
if (Fuel<53){
if (!flagkmAgeIGN) { kmAgeIGN = kmAge; flagkmAgeIGN =1;}
if (!flagFuelIGN) { FuelIGN = Fuel; Fuel_last = Fuel; flagFuelIGN = 1; }}}
else Serial.println (" ERROR!!!");
dataMessageEND = 0; MessageParse = 1; //mySerial_gauge.flush();
for (int i = 0; i < 34; i++) MessageRxGauge[i]=0; }} // очистка байтов массива
////////////////////////////////////////////////////////////////////
////////////////// работа с К-Line софт сериал 12-13 (7 контакт ОБД)
////////////////////////////////////////////////////////////////////
if (mySerial.available()) {
delay(195);
int k=0;
byte inbyte=0;
while( mySerial.available() && k < 110) {
inbyte = mySerial.read();
MessageRx[k] = inbyte;
k++; }
Serial.print ("Receive: ");
for (int i = 0; i < k; i++) {
Serial.print(MessageRx[i],HEX); Serial.print (" ");}
Serial.println ("");
if (MessageRx[2]==0x83 && MessageRx[3]==0xF1 && MessageRx[4]==0x11 && MessageRx[5]==0xC1 && MessageRx[6]==0x6B && MessageRx[7]==0x8F && MessageRx[8]==0x40) {Init=1;
timerenabledInit=0;
Serial.println (" Initialization OK!!!!: "); }
if (currentPage == '3'){
///////////////////////////////////////////////////////////////////////////////////////////////////
//Чтение и стирание ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////
//при получении этого сообщения выдавать на третий экран "NO ERROR"
if (MessageRx[4]==0x82 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]==0x00 && MessageRx[9]==0xDC){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 165, 145);
Serial.println (" NO DTC "); }
//при получении этого сообщения выдавать на третий экран "DTC BORRADO"
if (MessageRx[3]==0x83 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x54 && MessageRx[7]==0xFF && MessageRx[8]==0x00 && MessageRx[9]==0xD8){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 165, 145);
Serial.println (" DTC BORRADO "); }
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]>0){
Serial.println ("DTC is found!");
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx[8]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx[11+(i*3)],6) && bitRead(MessageRx[11+(i*3)],7)){ myGLCD.setColor (0,255,0);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx[11+(i*3)],7) && bitRead(MessageRx[11+(i*3)],6)) {myGLCD.setColor (255,0,0);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx[9+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx[9+(i*3)]<=0x0F&&MessageRx[9+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}
if (nolA)myGLCD.print(String (MessageRx[9+(i*3)],HEX), 246, (75+y));
else myGLCD.print(String (MessageRx[9+(i*3)],HEX), 230, (75+y));
if (MessageRx[10+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx[10+(i*3)]<=0x0F&&MessageRx[10+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;}
if (nolB)myGLCD.print(String (MessageRx[10+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx[10+(i*3)],HEX), 262, (75+y));}}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописываем формулы к данным ///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
else if (MessageRx[3]==0x80 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x4C && MessageRx[7]==0x61 && MessageRx[8]==0x01) {
//Barom = MessageRx[39];
L100 = (float)LHor*100.0/(float)Speed;
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
MAF = ((MessageRx[29]*256)+MessageRx[30])/10;
BoostPres = ((MessageRx[31]*256)+MessageRx[32])/1000.0;
RPM = (MessageRx[35]*256)+MessageRx[36];
EGRmg = ((MessageRx[37]*256)+MessageRx[38])/10.0;
BoostPresCom = ((MessageRx[41]*256)+MessageRx[42])/1000.0;
Speed = ((MessageRx[47]*256)+MessageRx[48])/100;
DesaInjQua = ((MessageRx[53]*256)+MessageRx[54])/100.0;
InjQua = ((MessageRx[55]*256)+MessageRx[56])/100.0;
StaDaliv = ((MessageRx[57]*256)+MessageRx[58])/100.0;
PumpRPM = (MessageRx[59]*256)+MessageRx[60];
EGRPul = ((MessageRx[65]*256)+MessageRx[66])/100.0;
SolenPul = ((MessageRx[67]*256)+MessageRx[68])/100.0;
SolenPre = ((MessageRx[73]*256)+MessageRx[74])/100.0;
DesInj = ((MessageRx[75]*3)+(MessageRx[76])/100.0)+0.3;
ActInj = ((MessageRx[19]*3)+(MessageRx[20])/100.0)+0.3;
//TempAir = ((MessageRx[77]*26)-278)+MessageRx[78]/10.0;
//Temp = ((MessageRx[17]*26)-278)+MessageRx[18]/10.0;
//TempOil = ((MessageRx[21]*26)-278)+MessageRx[22]/10.0;
//TempFuel = ((MessageRx[61]*26)-278)+MessageRx[62]/10.0;
//ниже идут расчетные формулы более точные чем те что закоментированы выше
int A = 0;
if (MessageRx[77]<=0x0A) A = 277;
if (MessageRx[77]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[77]>=0x0D) A = 279;
double B = MessageRx[78]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx[77]*26)-A)+cel;
if (MessageRx[17]<=0x0A) A = 277;
if (MessageRx[17]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[17]>=0x0D) A = 279;
B = MessageRx[18]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx[17]*26)-A)+cel;
if (MessageRx[21]<=0x0A) A = 277;
if (MessageRx[21]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[21]>=0x0D) A = 279;
B = MessageRx[22]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx[21]*26)-A)+cel;
if (MessageRx[61]<=0x0A) A = 277;
if (MessageRx[61]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[61]>=0x0D) A = 279;
B = MessageRx[62]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx[61]*26)-A)+cel;
timerenabledPID=0; }
for (int i = 0; i < 110; i++) MessageRx[i]=0; }} // очистка байтов массива
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//отправка запроса на диагностическое соединение
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initialization() {
Serial.println ("Otpravil zapros Init");
for (int i = 0; i < length5; i++) {
mySerial.write(messageInit[i]);
delay (5); }
delay (55); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//стартовая инициализация 7 пина ОБД
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fastinit() {
digitalWrite (TX, HIGH); // makes K-line high 3
delay(360); // wait for K-line to be clear 3
digitalWrite (TX, LOW); // makes K-line low 3
delay(25);
digitalWrite (TX, HIGH); // makes K-line high 3
delay(25); //last delay before first message
mySerial.begin(10400); } // baud rate of the OBD
///////////////////////////////////////////////////////////////////////////////////////////////////////
//запрос чтения и стирания ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////////
void Read() {
Serial.println ("Zapros error; ");
for (int i = 0; i < length8; i++) {
mySerial.write(messageREAD[i]);
delay (waitbyte); }}
void Erase() {
Serial.println ("Zapros erase; ");
for (int i = 0; i < length7; i++) {
mySerial.write(messageERASE[i]);
delay (waitbyte); }}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка тач кнопок
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописывает заголовки и кнопки на страницах
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawHomeScreen() {
line() ;
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии и текста красный
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.print("L/H", 10, 40);
myGLCD.print("L/A", 148, 40);
myGLCD.print("L/V", 10, 75);
myGLCD.print("L/M", 148, 75);
myGLCD.print("D/K", 10, 110);
myGLCD.print("D/L", 148, 110);
myGLCD.print("V/K", 10, 145);
myGLCD.print("V/L", 148, 145);
myGLCD.print("PUMP RPM", 82, 180);
myGLCD.print("Engi RPM", 82, 215);
myGLCD.print("D/La", 10, 180);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("Oil C", 300, 75);
myGLCD.print("Fuel C", 300, 110);
myGLCD.print("Inter C", 300, 145);
myGLCD.print("Exter C", 300, 180);
myGLCD.print("IntAirC", 300, 215);
buttonHome() ; //прорисовка кнопок
buttonINF1() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
Watch ();
myGLCD.print("Start of Delivery *CA:", 10, 40);
myGLCD.print("Desir inject Start *CA:", 10, 75);
myGLCD.print("Actua Inject Start *CA:", 10, 110);
myGLCD.print("Desir Inject Quan mg/s:", 10, 145);
myGLCD.print("Actu Inject Quant mg/s:", 10, 180);
myGLCD.print("MAF mg/s:", 10, 215);
myGLCD.print("Humedad %:", 255, 215);
buttonHome() ;
buttonINF2() ;
buttonCHECK() ; }
//-------------------------------------------------
void drawscreen_two() {
line() ;
Watch ();
myGLCD.print("Boost Press Bar:", 10, 40);
myGLCD.print("Boost Press Com Bar:", 10, 75);
myGLCD.print("EGR command mg/s:", 10, 110);
myGLCD.print("EGR Pulse Ratio %:", 10, 145);
myGLCD.print("Solenoide Pulse %:", 10, 180);
myGLCD.print("Solenoide Boost %:", 10, 215);
buttonHome() ;
buttonINF1() ;
buttonCHECK() ; }
//----------------------------------------------------------------------------
void drawscreen_three() {
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
buttonHome();
buttonERASE();
buttonREAD(); }
////////////////////////////////////////////////////////////////////////////////////////////////////////
//координаты тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка кнопок и координат тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonHome() {
myGLCD.setColor(0,0,0); // цвет кнопки черный
myGLCD.fillRect (1, 1, 80, 33); // расположение кнопки прямоугольника
myGLCD.setColor(255, 0, 0); // рамка будет красный
myGLCD.drawRect (1, 1, 80, 33); // кнопка будет рамкой
myGLCD.print("HOME", 1, 0); }// центровка строки
void buttonINF1() {
myGLCD.setColor(0,0,0);
myGLCD.fillRect (10, 255, 130, 310);
myGLCD.setColor(255, 0, 0);
myGLCD.drawRect (10, 255, 130, 310);
myGLCD.print("INF 1", 25, 265); }
void buttonINF2() {
myGLCD.setColor(0,0,0);
myGLCD.fillRect (180, 255, 300, 310);
myGLCD.setColor(255, 0, 0);
myGLCD.drawRect (180, 255, 300, 310);
myGLCD.print("INF 2", 200, 265); }
void buttonCHECK() {
myGLCD.setColor(0,0,0);
myGLCD.fillRect (350, 255, 470, 310);
myGLCD.setColor(255, 0, 0);
myGLCD.drawRect (350, 255, 470, 310);
myGLCD.print("CHECK", 375, 265);}
void buttonERASE() {
myGLCD.setColor(0,0,0);
myGLCD.fillRect (10, 255, 120, 310);
myGLCD.setColor(255, 0, 0);
myGLCD.drawRect (10, 255, 120, 310);
myGLCD.print("ERASE", 25, 265); }
void buttonREAD() {
myGLCD.setColor(0,0,0);
myGLCD.fillRect (350, 255, 470, 310);
myGLCD.setColor(255, 0, 0);
myGLCD.drawRect (350, 255, 470, 310);
myGLCD.print("READ", 375, 265); }
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,73,479,73); // линия горизонтальная
myGLCD.drawLine(1,108,479,108); // линия горизонтальная
myGLCD.drawLine(1,143,479,143); // линия горизонтальная
myGLCD.drawLine(1,178,479,178); // линия горизонтальная
myGLCD.drawLine(1,212,479,212); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); }// линия горизонтальная
/////////////////////////////////////////////////////////////////////////////////////////////
//верхняя часть экрана часы и дата отображается на всех экранах
/////////////////////////////////////////////////////////////////////////////////////////////
void Watch (){
DateTime now = rtc.now();
int m = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
myGLCD.setColor(255, 255, 255); //белый цвет цифры
if (date<10) {
myGLCD.print("0", 85, 0);
myGLCD.printNumI(now.day(), 100, 0); }
else if (date >=10) {
myGLCD.printNumI(now.day(), 85, 0); }
myGLCD.print("/", 115, 0);
if ( mon<10) {
myGLCD.print("0", 130, 0);
myGLCD.printNumI(now.month(), 145, 0);}
else if (mon >=10) {
myGLCD.printNumI(now.month(), 130, 0);}
myGLCD.print("/", 160, 0);
myGLCD.printNumI(now.year(), 175, 0);
if (hour<10) {
myGLCD.print("0",255, 0);
myGLCD.printNumI(now.hour(), 270, 0); }
else if(hour>=10){
myGLCD.printNumI(now.hour(), 255, 0); }
if (m<10) {
myGLCD.print("0",300, 0);
myGLCD.printNumI(now.minute(), 315, 0); }
else if (m>=10){
myGLCD.printNumI(now.minute(), 300, 0); }
myGLCD.setColor(255, 0, 0);
myGLCD.print("Km/h", 410, 0); }
void Temperature (){
h = dht.readHumidity();
t = dht.readTemperature();
sensors.requestTemperatures(); }
Блин второй день борюсь с отрисовкой и тачем. Выдернул меню из своего скетча, прописал тач, все работает. Вставлюю в основной скетчь строки для тачя, ЗАРАЗА НЕ РЕАГИРУЕТ. взял в скетче закоментил строку в лупе *receive ();, тач заработал но, отображение страноое вот
Выяснил что отрубает тачь(может не отрубает тач а просто все зависает потому что прорисовываются только заголовки и дата с временем но мигающих точек нет, а данные не прорисовываются и тач не работает, скорее всего зависает) сторока receive (); в воид луп,
а кривит изображение строки Temperature (); в воид сетуп и if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();} в воид луп
закоментив эти три сторки получаю гуд тачь и гуд прорисовка, единственное что присутствует видимость мигания обновления вывода данных, одн раз по времени и дате и три раза по данным, циклично, наверно потому что receive (); закоментирован в воид лупе.
скетч
/////////////////////////////////////////////////////////////////////////////////////////
//библиотеки
///////////////////////////////////////////////////////////////////////////////////////////
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
#include <UTFTGLUE.h>//use GLUE class and constructor
#include "TouchScreen.h"
#include <stdint.h>
#include <SPI.h>
#include <EEPROM.h>
MCUFRIEND_kbv tft;
#include "Fonts/Gobold_Bold14pt7b.h";
//Adafruit_GFX_Button buttonINF1, buttonINF2, buttonCHECK, buttonERASE, buttonREAD, buttonHome;
#define MINPRESSURE 200
#define MAXPRESSURE 1000
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
//датчик наружней температуры
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire);
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
///////////////////////////////////////////////////////////////////////////////////
//пины экрана и тача
///////////////////////////////////////////////////////////////////////////////////
//#define YP A1 // must be an analog pin, use "An" notation!
//#define XM A2 // must be an analog pin, use "An" notation!
//#define YM 6 // can be a digital pin
//#define XP 7 // can be a digital pin
UTFTGLUE myGLCD(0x1581,A2,A1,A3,A4,A0); //all dummy args
//оринтеровка тача под myGLCD.setRotation(3);
const int XP = 6, XM = A2, YP = A1, YM = 7;
//const int TS_LEFT = 136, TS_RT = 907, TS_TOP = 139, TS_BOT = 942;
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
uint16_t ID;
int x, y;
char currentPage;
float h;
float t;
bool Dvoet = 0;
//////////////////////////////////////////////////////////////////////////////
//все что касается OBD2
///////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
#define mySerial_gauge Serial2
#define TX_gauge 16
#define TX 13
SoftwareSerial mySerial (12, 13); //RХ,TХ
int length5 = 5;
int length6 = 6;
int length8 = 8;
int length7 = 7;
bool Init = 0;
bool InitGauge = 0;
bool dataMessageOK=0;
bool dataMessageEND = 0;
bool MessageParse = 0;
bool byte0 = 0;
bool byte1 = 0;
bool byte2 = 0;
int numberbyte = 0;
int PIDTime = 120; // задержка ожидания запроса следующего pid 2101, мс
int PresTime = 8000; // задержка между посылками запросов присутствия, мс
int waitbyte = 1; // задержка между отправкой байт в сообщении, мс
int waitbyte_gauge = 4;
int Datadelay = 50; // задержка между отрисовкой данных на LCD, мс
float L100M = 0; //расход на 100 км измеренный за поездку
float L100 = 0; //мгновенный расход литров на 100км
float LHor = 0; //мгновенный расход топлива литров в час
float L100SR = 0; //расход литров на 100км измеренный раз в интервал kmL
float L100SR_TFT = 0; // самый средний из расходов на 100км, он выводится на экран
int L100_Eeprom[11]= {10,10,10,10,10,10,10,10,10,10,10};
int FuelZamer[10]= {0}; // массив для измерения уровня (количества) топлива
int ZamerNumber = 0; // номер замера уровня (количества) топлива
int n_eeprom = 0; // текущий адрес ячейки еепром для записи расхода
int MAF = 0; //26,27 байты Sensor de flujo de aire en masa
float BoostPres = 0; //28,29 байты Presión de refuerzo
int RPM = 0; //32,33 байты Velocidad del motor
int EGRmg = 0; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
float BoostPresCom = 0; //38,39 байты Comando de presión de refuerzo
int Speed = 0; //44,45 байты Velocidad del vehículo
float DesaInjQua = 0; //50,51 байты Cantidad de inyección deseada
float InjQua = 0; //52,53 байты Cantidad de la inyección
float StaDaliv = 0; //54,55 байты Inicio de la entrega
int PumpRPM = 0; //56,57 байты Velocidad de la bomba
float EGRPul = 0; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
float SolenPul = 0; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
float SolenPre = 0; //70,71 байты Relación de impulsos Presión Electroválvula de presión
float DesInj = 0; //72,73 байты Inyección deseada Inicio
float ActInj = 0; //16,17 байты Inicio de la inyección real
int TempAir = 0; //74,75 байты Temperatura del aire de admisión
int Temp = 0; //14,15 байты Temperatura del refrigerante
int TempOil = 0; //18,19 байты Temperatura del aceite del motor
int TempFuel = 0; //58,59 байты Temperatura del combustible
//все что касается топлива
float Fuel = 0; //остаток топлива
float Fuel2 = 0; //остаток мгновенного топлива байт 16 , датчика в баке
int FuelIGN = 0; // количество топлвива в баке на момент включения зажигания
int Fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
float FuelTrip = 0; // количество литров топлива, израсходованное за один цикл включения зажигания
//все что касается километража
float kmAge = 0; //пробег, полученный со щитка приборов
int kmAgeIGN = 0; //пробег который был в момент включения зажигания
int kmAge_last = 0; // для формул
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
float kmTrip = 0; //пробег за один цикл включения зажигания
int kmL = 10; // интервал, через который будет происходить обновление среднего расхода на 100км
int km = 0; // переменная для расчетов
int kmeeprom = 10; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING = 0; // пробег до заправки на остатке топлива
int colerror = 0; //количество ошибок в правом верхнем углу третьего экрана
//float Barom = 0; // барометр
byte MessageRx[110] = {0}; // массив байтов принимаемого сообщения
byte MessageRxGauge[60] = {0}; // массив байтов принимаемого сообщения от щитка приборов
byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04}; // запрос инициализации
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1}; // запрос присутствия
byte messagePids[6] = {0x82,0x11,0xF1,0x21,0x01,0xA6}; // запрос пид 2101
byte messageREAD[8] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
byte messageERASE[7] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98}; // стирание ошибок
unsigned long prevPID = 0;
unsigned long prevPIDgauge = 0;
unsigned long prevTemperature = 0;
unsigned long prevpres = 0;
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
unsigned long prevData = 0;
unsigned long TimewaitPID, timerwaitPID = 0;
bool timerenabledPID = 0;
#define TIMEREXPIRED_PID (TimewaitPID - timerwaitPID)> 200 // здесь задержка на ожидание правильного ответа пидов, мс
unsigned long TimewaitInit, timerwaitInit = 0;
bool timerenabledInit = 0;
#define TIMEREXPIRED_Init (TimewaitInit - timerwaitInit)> 500 // здесь задержка на ожидание ответа об удачной инициализации, мс
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
uint16_t ID = myGLCD.readID();
if (ID == 0xD3D3) ID = 0x9486; // write-only shield
myGLCD.begin(ID);
Serial.begin(115200);
mySerial.begin(10400);
Wire.begin();
rtc.begin();
dht.begin();
sensors.begin();
myGLCD.InitLCD(3);
myGLCD.clrScr();
myGLCD.setFont(&Gobold_Bold14pt7b);
//загрузка стартовой страницы
currentPage = '0';
drawHomeScreen();
//подсчет среднеарифметического усредненного расхода
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.0;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить времая и дату, залить в ардуино. в скетче закоментировать
// обратно и залить еще раз, иначе каждый раз будет по новой выствлятся это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2017, 7, 21, 13, 57, 0));
//Temperature ();
pinMode(TX, OUTPUT);
pinMode(TX_gauge, OUTPUT);
fastinit();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP FIN
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LOOP
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
TimewaitPID = millis ();
TimewaitInit = millis ();
if (!Init) { if (!timerenabledInit){ timerwaitInit=TimewaitInit; timerenabledInit=1; initialization(); }
else if (TIMEREXPIRED_Init) timerenabledInit=0;}
else { if (currentPage != '3'){ // если открыта страница 0,1 или 2 шлем запрос пид2101, если страница 3 - шлем запрос присутствия
if (millis() - prevPID > PIDTime) { PIDs(); prevPID = millis(); }}
else if (millis() - prevpres > PresTime) {present(); prevpres = millis();}}
if (!InitGauge) {Serial.println ("Otpravil zapros adress Gauge");
digitalWrite (TX_gauge, HIGH); delay (500);
digitalWrite (TX_gauge, LOW); delay (20);
digitalWrite (TX_gauge, HIGH ); delay (15);
digitalWrite (TX_gauge, LOW); delay (5);
digitalWrite (TX_gauge, HIGH); delay (5);
mySerial_gauge.begin(9600);}
//receive ();
if (millis() - prevWatch > 3000) { Watch (); prevWatch = millis(); Trip ();}
//if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();}
if (millis() - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 285, 0);} else {myGLCD.print(" ", 285, 0);} prevDvoet = millis(); Dvoet=!Dvoet;}
Menu();
LCDDataPrint();}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//BOID TRIP//////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void Trip () {
if (flagkmAgeIGN){
FuelTrip = FuelIGN - Fuel;
if (kmAge>kmAgeIGN) kmTrip = kmAge - kmAgeIGN;
if (kmAge<kmAgeIGN) kmTrip = 2000 - (kmAgeIGN - kmAge); // 2000 это через сколько км у тебя суточный пробег сбрасывается на ноль, поменяй если другое число
if (kmAge==kmAgeIGN) kmTrip = 0;
//подсчет расхода на 100км за поездку
L100M = ((float)FuelTrip*100.00)/(float)kmTrip;
if (L100M<0) L100M = 0;
if (L100M>99) L100M = 99;
// ниже цикл считает среднеарифметический расход из еепром раз в пробег, указанный в переменной kmeeprom
if (kmTrip-kmTFT>kmeeprom) {kmTFT = kmTrip;
// тут считаем среднеарифметический усредненного расход из ячеек еепром
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;}
// ниже цикл считает расход топлива за пробег, указанный в переменной kmL, здесь же запись в ячейки еепром
if (kmTrip-km>kmL) {km=kmTrip;
L100SR = ((float)(Fuel_last-Fuel)*100.00)/(float)kmL; // расход/100км - обновляется раз в 10км, меняется км в int kmL = 10;
Fuel_last = Fuel; // сохранение параметров с последнего измерениея
if (L100SR<0) L100SR = 0;
if (L100SR>99) L100SR = 99;
//расчет остатка километров в баке
if (L100SR>0) kmREFUELING=((float)Fuel*100.0)/(float)L100SR; //если средний расход больше нуля, то расчитывать км в баке из него
else kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT; //если ноль или ментше то расчитывать км в баке с устредненного расхода
// тут записываем L100SR последовательно в одну из 11 ячеек еепром
//EEPROM.write (12,n_eeprom); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
n_eeprom = EEPROM.read (12); // в ячейке 12 хранится № текущей ячейки для записи расхода, чтобы где остановился при выкл питания, от туда и продолжил
EEPROM.write(n_eeprom, L100SR*10);
n_eeprom++; if (n_eeprom>10) n_eeprom=0;
EEPROM.write (12,n_eeprom); }}}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//BOID LCDDATAPRINT. прописываем данные и их расположение и цвет/////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void LCDDataPrint(){
unsigned long curData = millis();
if (millis() - prevData > Datadelay){
myGLCD.setColor(255, 255, 255); //цвет текста
myGLCD.printNumI(Speed, 350, 0, 3);
//----------------------------------------------------------
//страниц HOME
//----------------------------------------------------------
if (currentPage == '0') {
myGLCD.printNumF(LHor, 1, 60, 40, '.',5);
myGLCD.printNumF(L100, 1, 210, 40,'.',5 );
myGLCD.printNumF(L100M, 1, 60, 75,'.',5 );
myGLCD.printNumF(L100SR_TFT, 1, 210, 75,'.',5 );
myGLCD.printNumI(kmREFUELING, 60, 110,5 );
//if (Fuel<53)
myGLCD.printNumF(Fuel, 1, 210, 110,'.',5);
//else myGLCD.print("MAX", 210, 110);
myGLCD.printNumF(kmTrip, 1, 60, 145,'.',5);
myGLCD.printNumF(FuelTrip, 1, 210, 145,'.',5);
myGLCD.printNumI(PumpRPM, 210, 180,5);
myGLCD.printNumI(RPM, 210, 215,5);
myGLCD.printNumF(Fuel2, 1, 0, 215,'.',5);
myGLCD.printNumI(Temp, 415, 40, 3);
myGLCD.printNumI(TempOil, 415, 75, 3);
myGLCD.printNumI(TempFuel, 415, 110,3);
myGLCD.printNumI(sensors.getTempCByIndex(0), 415, 145 , 3);
myGLCD.printNumI(t, 415, 180, 3);
myGLCD.printNumI(TempAir, 415, 215, 3); }
//----------------------------------------------------------
//страниц INF1
//----------------------------------------------------------
if (currentPage == '1') {
myGLCD.printNumF(StaDaliv,1, 395, 40,'.', 3);
myGLCD.printNumF(DesInj,1, 395, 75, '.', 4);
myGLCD.printNumF(ActInj,1, 395, 110,'.', 4);
myGLCD.printNumF(DesaInjQua,1, 395, 145,'.', 4);
myGLCD.printNumF(InjQua,1, 395, 180,'.', 4);
myGLCD.printNumI(MAF, 170, 215, 4);
myGLCD.printNumF(h, 1, 415, 215); }
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
myGLCD.printNumF(BoostPres,1, 395, 40,'.', 4);
myGLCD.printNumF(BoostPresCom,1, 395, 75,'.', 4);
myGLCD.printNumI(EGRmg, 395, 110, 4);
myGLCD.printNumF(EGRPul,1, 395, 145,'.',3);
myGLCD.printNumF(SolenPul, 1, 395, 180,'.', 4);
myGLCD.printNumF(SolenPre, 0, 395, 215,'.', 3); }
prevData = millis(); }}
///////////////////////////////////////////////////////////////////////////
//BOID PIDs//отправка запроса пид 2101/////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void PIDs() {
Serial.println ("Otpravil zapros 21 01");
for (int i = 0; i < length6; i++) {
mySerial.write(messagePids[i]);
delay (waitbyte); }}
///////////////////////////////////////////////////////////////////////////
//BOID PIDsGAUGR//отправка запроса на панель приборов//////////////////////
///////////////////////////////////////////////////////////////////////////
void PIDsGauge() {
Serial.println (" Otpravil zapros 02 11 na panel");
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write(byte(0)); delay (1);
mySerial_gauge.write (0x13); }
///////////////////////////////////////////////////////////////////////////
//BOID PIDsGAUGR//отправка запроса присутствия/////////////////////////////
///////////////////////////////////////////////////////////////////////////
void present() {
Serial.println ("Otpravil zapros Present");
for (int i = 0; i < length5; i++) {
mySerial.write(messagePresent[i]);
delay (waitbyte); }}
/////////////////////////////////////////////////////////////////////////////////////////////
//получение данных от ЭБУ, разборка входящих сообщений
/////////////////////////////////////////////////////////////////////////////////////////////
void receive () {
///////////////////////////////////////////////////////////////////////
////////////////// работа с К-Line софт сериал 16-17 (12 контакт ОБД)
///////////////////////////////////////////////////////////////////////
while(!InitGauge){
if (mySerial_gauge.available()) {
byte inByte = mySerial_gauge.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {mySerial_gauge.write (0x7F); delay (1);}
if (inByte==0xF0) {
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write (0x00); delay (1);
mySerial_gauge.write (0x13); delay (1); InitGauge=1; }}}
MessageParse = 0;
while (InitGauge && !MessageParse) {
if (!dataMessageOK) {
if (mySerial_gauge.read() == 0x23) {byte0=1; delay (waitbyte_gauge); }
if (mySerial_gauge.read() == 0xA1 && byte0) {byte1=1; delay (waitbyte_gauge);}
else byte0=0;
if (mySerial_gauge.read() == 0x04 && byte0 && byte1) {byte2=1; delay (waitbyte_gauge);}
else {byte0=0; byte1=0;}
if (byte0 && byte1 && byte2) {dataMessageOK = 1; byte0=0; byte1=0; byte2=0;}
numberbyte=0;}
else { if (mySerial_gauge.available()>0) { MessageRxGauge[numberbyte] = mySerial_gauge.read(); numberbyte++; delayMicroseconds (250);}
if (numberbyte==34) {dataMessageEND = 1; dataMessageOK = 0; }}
if (dataMessageEND) {
int crc = ( ( unsigned int )MessageRxGauge[32] << 8 ) | MessageRxGauge[33]; // парсинг контрольной суммы из 2 последних байт
int CRC =200;
for (int i = 0; i < 32; i++) CRC = CRC + MessageRxGauge[i]; // подсчет контрольной суммы байт от 0 до 31
Serial.print (" ReceiveGauge: ");
for (int i = 0; i < 34; i++) {
Serial.print(MessageRxGauge[i],HEX); Serial.print (" ");}
//при получении сообщения БЕЗ ошибок с данными от панели приборов, запишем в переменные остаток топлива и пробег
if (CRC==crc) {Serial.println (" OK!!!");
Fuel2 = MessageRxGauge[16]/2.0;
if (!flagFuelIGN) { Fuel = MessageRxGauge[16]/2.00; kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;} //стартовая запись литров в баке для подсчета затраченных литро
else Fuel = MessageRxGauge[17]/2.0; //для устреднения болтания в баке закоментировать эту строку, а раскоментировать ниже
//для усреднения болтания топлива в баке, раскоментировать, высчитывает среднее
/*else { FuelZamer[ZamerNumber] = MessageRxGauge[17]/2.00;
if (ZamerNumber==9) {
Fuel = 0 ;
for (int i = 0; i < 10; i++) Fuel = Fuel + FuelZamer[i];
Fuel = (float)Fuel/10.0;}
ZamerNumber++; if (ZamerNumber>9) ZamerNumber = 0;}
*/
kmAge = (MessageRxGauge[23]+(MessageRxGauge[24]*256))/10.0; //суточный пробег с панели приборов
//бак у меня на 59 литров, а датчик показывает максимально 53 литра. для этого эта формула
//если у вас тоже датчик имеет лимит то подправте 53 на свой лимит.
//если ваш датчик показывает одинаково с полным баком то закоментировать три нижние строки.
if (Fuel<53){
if (!flagkmAgeIGN) { kmAgeIGN = kmAge; flagkmAgeIGN =1;}
if (!flagFuelIGN) { FuelIGN = Fuel; Fuel_last = Fuel; flagFuelIGN = 1; }}}
else Serial.println (" ERROR!!!");
dataMessageEND = 0; MessageParse = 1; //mySerial_gauge.flush();
for (int i = 0; i < 34; i++) MessageRxGauge[i]=0; }} // очистка байтов массива
////////////////////////////////////////////////////////////////////
////////////////// работа с К-Line софт сериал 12-13 (7 контакт ОБД)
////////////////////////////////////////////////////////////////////
if (mySerial.available()) {
delay(195);
int k=0;
byte inbyte=0;
while( mySerial.available() && k < 110) {
inbyte = mySerial.read();
MessageRx[k] = inbyte;
k++; }
Serial.print ("Receive: ");
for (int i = 0; i < k; i++) {
Serial.print(MessageRx[i],HEX); Serial.print (" ");}
Serial.println ("");
if (MessageRx[2]==0x83 && MessageRx[3]==0xF1 && MessageRx[4]==0x11 && MessageRx[5]==0xC1 && MessageRx[6]==0x6B && MessageRx[7]==0x8F && MessageRx[8]==0x40) {Init=1;
timerenabledInit=0;
Serial.println (" Initialization OK!!!!: "); }
if (currentPage == '3'){
///////////////////////////////////////////////////////////////////////////////////////////////////
//Чтение и стирание ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////
//при получении этого сообщения выдавать на третий экран "NO ERROR"
if (MessageRx[4]==0x82 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]==0x00 && MessageRx[9]==0xDC){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 165, 145);
Serial.println (" NO DTC "); }
//при получении этого сообщения выдавать на третий экран "DTC BORRADO"
if (MessageRx[3]==0x83 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x54 && MessageRx[7]==0xFF && MessageRx[8]==0x00 && MessageRx[9]==0xD8){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 165, 145);
Serial.println (" DTC BORRADO "); }
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]>0){
Serial.println ("DTC is found!");
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx[8]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx[11+(i*3)],6) && bitRead(MessageRx[11+(i*3)],7)){ myGLCD.setColor (0,255,0);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx[11+(i*3)],7) && bitRead(MessageRx[11+(i*3)],6)) {myGLCD.setColor (255,0,0);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx[9+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx[9+(i*3)]<=0x0F&&MessageRx[9+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}
if (nolA)myGLCD.print(String (MessageRx[9+(i*3)],HEX), 246, (75+y));
else myGLCD.print(String (MessageRx[9+(i*3)],HEX), 230, (75+y));
if (MessageRx[10+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx[10+(i*3)]<=0x0F&&MessageRx[10+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;}
if (nolB)myGLCD.print(String (MessageRx[10+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx[10+(i*3)],HEX), 262, (75+y));}}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописываем формулы к данным ///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
else if (MessageRx[3]==0x80 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x4C && MessageRx[7]==0x61 && MessageRx[8]==0x01) {
//Barom = MessageRx[39];
L100 = (float)LHor*100.0/(float)Speed;
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
MAF = ((MessageRx[29]*256)+MessageRx[30])/10;
BoostPres = ((MessageRx[31]*256)+MessageRx[32])/1000.0;
RPM = (MessageRx[35]*256)+MessageRx[36];
EGRmg = ((MessageRx[37]*256)+MessageRx[38])/10.0;
BoostPresCom = ((MessageRx[41]*256)+MessageRx[42])/1000.0;
Speed = ((MessageRx[47]*256)+MessageRx[48])/100;
DesaInjQua = ((MessageRx[53]*256)+MessageRx[54])/100.0;
InjQua = ((MessageRx[55]*256)+MessageRx[56])/100.0;
StaDaliv = ((MessageRx[57]*256)+MessageRx[58])/100.0;
PumpRPM = (MessageRx[59]*256)+MessageRx[60];
EGRPul = ((MessageRx[65]*256)+MessageRx[66])/100.0;
SolenPul = ((MessageRx[67]*256)+MessageRx[68])/100.0;
SolenPre = ((MessageRx[73]*256)+MessageRx[74])/100.0;
DesInj = ((MessageRx[75]*3)+(MessageRx[76])/100.0)+0.3;
ActInj = ((MessageRx[19]*3)+(MessageRx[20])/100.0)+0.3;
//TempAir = ((MessageRx[77]*26)-278)+MessageRx[78]/10.0;
//Temp = ((MessageRx[17]*26)-278)+MessageRx[18]/10.0;
//TempOil = ((MessageRx[21]*26)-278)+MessageRx[22]/10.0;
//TempFuel = ((MessageRx[61]*26)-278)+MessageRx[62]/10.0;
//ниже идут расчетные формулы более точные чем те что закоментированы выше
int A = 0;
if (MessageRx[77]<=0x0A) A = 277;
if (MessageRx[77]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[77]>=0x0D) A = 279;
double B = MessageRx[78]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx[77]*26)-A)+cel;
if (MessageRx[17]<=0x0A) A = 277;
if (MessageRx[17]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[17]>=0x0D) A = 279;
B = MessageRx[18]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx[17]*26)-A)+cel;
if (MessageRx[21]<=0x0A) A = 277;
if (MessageRx[21]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[21]>=0x0D) A = 279;
B = MessageRx[22]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx[21]*26)-A)+cel;
if (MessageRx[61]<=0x0A) A = 277;
if (MessageRx[61]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[61]>=0x0D) A = 279;
B = MessageRx[62]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx[61]*26)-A)+cel;
timerenabledPID=0; }
for (int i = 0; i < 110; i++) MessageRx[i]=0; }} // очистка байтов массива
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//отправка запроса на диагностическое соединение
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initialization() {
Serial.println ("Otpravil zapros Init");
for (int i = 0; i < length5; i++) {
mySerial.write(messageInit[i]);
delay (5); }
delay (55); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//стартовая инициализация 7 пина ОБД
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fastinit() {
digitalWrite (TX, HIGH); // makes K-line high 3
delay(360); // wait for K-line to be clear 3
digitalWrite (TX, LOW); // makes K-line low 3
delay(25);
digitalWrite (TX, HIGH); // makes K-line high 3
delay(25); //last delay before first message
mySerial.begin(10400); } // baud rate of the OBD
///////////////////////////////////////////////////////////////////////////////////////////////////////
//запрос чтения и стирания ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////////
void Read() {
Serial.println ("Zapros error; ");
for (int i = 0; i < length8; i++) {
mySerial.write(messageREAD[i]);
delay (waitbyte); }}
void Erase() {
Serial.println ("Zapros erase; ");
for (int i = 0; i < length7; i++) {
mySerial.write(messageERASE[i]);
delay (waitbyte); }}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка тач кнопок
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Menu () {
if (currentPage == '0') {
TouchHOME();
TouchINF1();
TouchINF2();
TouchCHECK(); }
if (currentPage == '1') {
TouchHOME();
TouchINF2();
TouchCHECK(); }
if (currentPage == '2') {
TouchHOME();
TouchINF1();
TouchCHECK(); }
if (currentPage == '3') {
TouchHOME();
TouchREAD();
TouchERASE(); }}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописывает заголовки и кнопки на страницах
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawHomeScreen() {
line() ;
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии и текста красный
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(75,178,75,247); // линия вертикальная
myGLCD.print("L/H", 10, 40);
myGLCD.print("L/A", 148, 40);
myGLCD.print("L/V", 10, 75);
myGLCD.print("L/M", 148, 75);
myGLCD.print("D/K", 10, 110);
myGLCD.print("D/L", 148, 110);
myGLCD.print("V/K", 10, 145);
myGLCD.print("V/L", 148, 145);
myGLCD.print("PUMP RPM", 82, 180);
myGLCD.print("ENGI RPM", 82, 215);
myGLCD.print("D/La", 10, 180);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("OIL C", 300, 75);
myGLCD.print("FUEL C", 300, 110);
myGLCD.print("INTER C", 300, 145);
myGLCD.print("EXTER C", 300, 180);
myGLCD.print("INTAIR C", 300, 215);
myGLCD.print("INF 1", 55, 270);
myGLCD.print("INF 2", 215, 270);
myGLCD.print("CHECK", 365, 270);
myGLCD.print("HOME", 10, 5);
myGLCD.print("Km/h", 410, 3);
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии и текста красный
myGLCD.print("Start of Delivery *CA:", 10, 40);
myGLCD.print("Desir inject Start *CA:", 10, 75);
myGLCD.print("Actua Inject Start *CA:", 10, 110);
myGLCD.print("Desir Inject Quan mg/s:", 10, 145);
myGLCD.print("Actu Inject Quant mg/s:", 10, 180);
myGLCD.print("MAF mg/s:", 10, 215);
myGLCD.print("Humedad %:", 255, 215);
myGLCD.print("INF 2", 215, 270);
myGLCD.print("CHECK", 365, 270);
myGLCD.print("HOME", 10, 5);
myGLCD.print("Km/h", 410, 3);
}
//-------------------------------------------------
void drawscreen_two() {
line() ;
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии и текста красный
myGLCD.print("Boost Press Bar:", 10, 40);
myGLCD.print("Boost Press Com Bar:", 10, 75);
myGLCD.print("EGR command mg/s:", 10, 110);
myGLCD.print("EGR Pulse Ratio %:", 10, 145);
myGLCD.print("Solenoide Pulse %:", 10, 180);
myGLCD.print("Solenoide Boost %:", 10, 215);
myGLCD.print("INF 1", 55, 270);
myGLCD.print("CHECK", 365, 270);
myGLCD.print("HOME", 10, 5);
myGLCD.print("Km/h", 410, 3);
}
//----------------------------------------------------------------------------
void drawscreen_three() {
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
myGLCD.print("ERASE", 55, 270);
myGLCD.print("READ", 365, 270);
myGLCD.print("HOME", 10, 5);
myGLCD.print("Km/h", 410, 3);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//кнопки тач . координаты и переходы
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void TouchHOME(){
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > 10 && p.z < 1000)
{if (p.x > 140 && p.x < 320 && p.y > 140 && p.y < 260 && p.z > MINPRESSURE && p.z < MAXPRESSURE)
{ myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect(1, 1, 77, 37);
currentPage = '0';
myGLCD.clrScr();
drawHomeScreen();
x = 0;
y = 0;
p.z = 0;}}
else {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect(1, 1, 77, 37);}
}
void TouchINF1(){
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > 10 && p.z < 1000)
{
if (p.x > 150 && p.x < 450 && p.y > 770 && p.y < 890 && p.z > MINPRESSURE && p.z < MAXPRESSURE)
{ myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect(15, 255, 145, 310);
currentPage = '1';
myGLCD.clrScr();
drawscreen_one();
x = 0;
y = 0;
p.z = 0;}}
else {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect(15, 255, 145, 310);}
}
void TouchINF2(){
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > 10 && p.z < 1000)
{
if (p.x > 450 && p.x < 680 && p.y > 770 && p.y < 890 && p.z > MINPRESSURE && p.z < MAXPRESSURE)
{ myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect(175, 255, 305, 310);
currentPage = '2';
myGLCD.clrScr();
drawscreen_two();
x = 0;
y = 0;
p.z = 0;}}
else {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect(175, 255, 305, 310);}
}
void TouchCHECK(){
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > 10 && p.z < 1000)
{
if (p.x > 690 && p.x < 950 && p.y > 770 && p.y < 890 && p.z > MINPRESSURE && p.z < MAXPRESSURE)
{ myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect(335, 255, 465, 310);
currentPage = '3';
myGLCD.clrScr();
drawscreen_three();
x = 0;
y = 0;
p.z = 0;}}
else {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect(335, 255, 465, 310);}
}
void TouchREAD(){
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > 10 && p.z < 1000)
{
if (p.x > 690 && p.x < 950 && p.y > 770 && p.y < 890 && p.z > MINPRESSURE && p.z < MAXPRESSURE)
{ myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect(335, 255, 465, 310);
Read();
x = 0;
y = 0;
p.z = 0;}}
else {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect(335, 255, 465, 310);}
}
void TouchERASE(){
TSPoint p = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > 10 && p.z < 1000)
{
if (p.x > 150 && p.x < 450 && p.y > 770 && p.y < 890 && p.z > MINPRESSURE && p.z < MAXPRESSURE)
{ myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect(15, 255, 145, 310);
Erase();
x = 0;
y = 0;
p.z = 0;}}
else {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect(15, 255, 145, 310);}
}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,73,479,73); // линия горизонтальная
myGLCD.drawLine(1,108,479,108); // линия горизонтальная
myGLCD.drawLine(1,143,479,143); // линия горизонтальная
myGLCD.drawLine(1,178,479,178); // линия горизонтальная
myGLCD.drawLine(1,212,479,212); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); }// линия горизонтальная
/////////////////////////////////////////////////////////////////////////////////////////////
//верхняя часть экрана часы и дата отображается на всех экранах
/////////////////////////////////////////////////////////////////////////////////////////////
void Watch (){
DateTime now = rtc.now();
int m = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
myGLCD.setColor(255, 255, 255); //белый цвет цифры
if (date<10) {
myGLCD.print("0", 85, 3);
myGLCD.printNumI(now.day(), 100, 3); }
else if (date >=10) {
myGLCD.printNumI(now.day(), 85, 3); }
myGLCD.print("/", 115, 3);
if ( mon<10) {
myGLCD.print("0", 130, 3);
myGLCD.printNumI(now.month(), 145, 3);}
else if (mon >=10) {
myGLCD.printNumI(now.month(), 130, 3);}
myGLCD.print("/", 160, 3);
myGLCD.printNumI(now.year(), 175, 3);
if (hour<10) {
myGLCD.print("0",255, 3);
myGLCD.printNumI(now.hour(), 270, 3); }
else if(hour>=10){
myGLCD.printNumI(now.hour(), 255, 3); }
if (m<10) {
myGLCD.print("0",300, 3);
myGLCD.printNumI(now.minute(), 315, 3); }
else if (m>=10){
myGLCD.printNumI(now.minute(), 300, 3); }
}
void Temperature (){
h = dht.readHumidity();
t = dht.readTemperature();
sensors.requestTemperatures(); }
копаю дальше. по ходу гдето есть конфликт
нашел кусок который все валит,он в начале void receive ()
Не могу понять в чем причина зависания. MaksVV помоги разобратся, ПЛИЗ
Все я сдаюсь. конфликт куска что выше, не могу понять, мерцание при обновлении не могу убрать, датчик температуры что ломает отображение так и не дошел. Может через неделю на свежую голову просмотрю.
не может соединиться со щитком приборов по какой либо причине. А там цикл while, т.е. в нем пытается соединиться со щитком , и если тщетно, то это будет бесконечно, соотвественно ничего другое в этот момент не работает, и ты видишь это как зависание. Смотри что в порту Serial при этом пишет. В скетче присутствует вывод туда отладки.
MaksVV вообщем думаю нужно разбирать панель и на живую ставить экран и уже смотреть че да как.... С перового июля буду целый месяц иметь время, займусь этим. Будет видно на живую. расчитываю на твою помощь. если в отпуск не уедешь:).
не макс. у меня все закрыто в одну коробку и коробка в панели. нужно снимать панель и вынемать весь бортовик с панели. а там все припаяно и приклеено клеевым пистолетом. только полная разборка и замена экрана. и тестить
ну ты же как то новый скетч тестил? куда ты его подключал? если ты просто новый экран тестил, не подключая к к-лайнам, то тогда все понятно. Возьми закоментируй эти циклы while, которые нужны для коннекта по к-лайн PCM и приборки, тогда можно и без коннектов к к-лайну потестить экран
да макс так и было. :) без ничего. просто тестил настраивал и подправлял отображение на экране. и все отлично работает. кроме этого нюанса. по этому и говорю только ставить и на живую. 1 июля буду разберать и менять. надеюсь все пройдет гладко
Потрясающе, что вы с MaksVV за 3 месяца смогли создать рабочий скетч для БК!!! Я сам давно хотел сделать для своей Нексии N150 БК, правда на PicBasicPro. Не хватило знаний, теперь делаю на Ардуино. Язык Си для меня гораздо сложнее, поэтому скетчи MaksVV очень помогли. Кстати, у моей машины тоже протокол ISO 14230 Fast Init 10400 и адреса запросов совпадают с Вашими! Так что для меня это подарок! Отдельное спасибо MaksVV за то, что он помог нескольким новичкам с программированием БК!
по поводу оптимизации скетча, в частности обмена по к-лайн (KWP) . Почитайте сообщение #1201. Там довольно важная информация по протоколу. А то у ТС когда мы скетч делали бортовика до этого ещё не дошли, и действовали как слепые котята, используя delay в сотни миллисек и борясь из-за этого с паразитными непонятными FF байтами, которых на шине по факту и не было, а был это результат некорректного формирования кадров из шины.
После бортовика ТС, я ещё способстовал проекту бортовика в этой теме Targitai на опель вектре. Дак вот там уже фигурируют скетчи обмена по к-лайн более продвинутые, с отсутствием delay в сотни миллисекунд, с проверкой контрольной суммы, и с автоматическим переподключением к PCM, если связь по какойто причине прервалась. например скетч #1321. Жаль что Targitai вроде как дело до конца так и не довёл. А ведь немного оставалось.
Спасибо, MaksVV, обязательно посмотрю. Сам пару лет назад научился писать код с параллельными процессами, но потом слетел винт-многое потерял, а главное потерял интерес. Так что в программировании меня отбросило далеко назад. ) Если все-таки доделаю БК, то выложу что получилось. Главное, чтобы мне жена не отдала свой Дастер, а то проект загнется, ведь там БК уже есть! )))))
БК для Нексии заработал на индикаторе пока в текстовом режиме на основе скетча №157. Также на основе этого скетча написал скетч с запросами поддерживаемых PIDов. Оказалось что из 196 PIDов 1-го сервиса на моей машине поддерживаются только 18! (1, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 17, 19, 20, 21, 28, 32 и 33). Нет ни Мафа, ни бортового напряжения. )))) Вот теперь вопрос как из этих данных рассчитать мгновенный расход и расход на 100 км? Кучу инета перелопатил. Нашел только как рассчитать Маф через Мап. Если есть у кого подходящие формулы-поделитесь, пож-та!
по всей видимости вы решили черпать информацию из стандартных обд2 PIDов. Но лучше её брать из PIDа протокола автопроизводителя. Обычно это один длинный PID, который содержит в себе все диагностические параметры сразу. Расшаривается этот пид с помощью снифа диагностической сессии диагностики и PCM. А также эмулятора PCM.
Нексия N150 DOHC 1.8л 16-клапанная, двигатель Sirius 42. Не знаю что такое эмулятор PCM. Вообще у меня есть лог соединения БК на основе нетбука программой ChevroletExplorer, там запрос инициализации 81 11 F1 81 04.
Порт открыт процессом "CheviExplorer.exe" (PID: 608)
Порт закрыт
Порт открыт процессом "CheviExplorer.exe" (PID: 608)
и зачем нужен MAF ? вам же не воздух нужно рассчитать, а топливо.
вам нужно искать в параметрах расход топлива кг/ч, (с учетом плотности бензина посчитаете л/ч). Но иногда такой параметр отсутствует, тогда вам нужна цикловая подача топлива, обычно измеряется мл/такт (цикл), либо г/такт(цикл).
Обороты ДВС это рабочие циклы в минуту, переводим это в час получаем циклы в час. Перемножаем обороты и цикловую подачу, получаем тот же мл (или л)/ч. если в г/ч то с помощью плотности переводим в л/ч. и поделить на 2 , т.к. ДВС 4 тактный
Name,ShortName,ModeAndPID,Equation,Min Value,Max Value,Units,Header
,, Этот конфиг разработан специально для Chevrolet Aveo Седан T255 1.2V 16V с ЭБУ Sirius D42R
,, Частично будет совпадать для других машин на этом же ЭБУ, таких как:
,, Daewoo Matiz, Chevrolet Lacetti
,, Все строчки с запятой вначале отключены.
,, PIDы для АКПП отключены, за ненадобностью лично мне
,, Для включения строчки в список дополнительных параметров необходимо стереть запятую в начале строки.
,, wosk, 2014
,,PID $01 из стандарта J1979
t ОЖ,ЕСТ,0105,A-40,-50,140,C,
t впуска,IAT,010f,A-40,-50,140,C,
МАР,МАР,010b,A,0,255,kPa,
RPM,RPM,010c,(A*256+B)/4,0,16000,,
Speed,Speed,010d,A,0,255,km/h,
ДЗ%,TPS,0111,A/255*100,0,100,%,
УОЗ,УОЗ,010e,(A-128)/2,-64,64,deg,
FTBb1s1,FTBb1s1,0114,(B-128)/128*100,0,100,%,
LTFT1,LTFT1,0107,(A-128)/128*100,0,100,%,
STFT1,STFT1,0106,(A-128)/128*100,0,100,%,
LoadEng,LoadEng,0104,A/255*100,0,100,%,
Closed Loop,CL,0103,{A:1}+{A:4},0,1,Off/On,
t ОЖ,ЕСТ,2102,A/255*192-49,-50,140,C,
t на впуске,IAT,2102,B/255*192-49,-50,140,C,
ДЗ%,TPS,2102,C/255*100,0,100,%,
Напряжение,Voltage,2102,D/8.88,0,16,V,
Скорость,Speed,2102,E,0,255,km/h,
Обороты,RPM,2102,(F<8)+G,0,9000,rpm,
Барометрическое давление,BARO,2102,H/255*119,0,119,kPa,
Давление во впускном коллекторе,МАР,2102,J/255*119,0,119,kPa,
Массовый расход воздуха,MAF,2102,((L<8)+M)/47,0,1400,mg/t,
Длительность впрыска пусковая,InjDurSt,2102,((N<8)+O)/62.5,0,1050,ms,
Длительность впрыска текущая,InjDur,2102,((P<8)+Q)/250,0,0,ms,
Коррекция длительности впрыска,Corr Inj,2102,(signed(T)*256+U)/250,0,65535,ms,
Передача МКПП,Gear,2102,V,0,5,,
,Режим АКПП,AKPP,2102,W,0,255,,
Скважность продувки адсорбера,AdsFlow,2102,X/255*100,0,100,%,
Рециркуляция отработаных газов,EGR,2102,Y/255*100,0,100,%,
Давление в системе кондиционирования,ACP,2102,AB*12,0,3100,kPa,
,Fuel%,Fuel%,2102,Z/255*100,0,100,%,
,,,,,, напряжения
Напр.дат.ТВпуск,VoltIAT,2101,((C<8)+D)/205,0,0,V,
,,, мб неправильный коэффициент (Макс 5В)
Напр.дат.РХХ,VoltIAR,2101,((E<8)+F)/205,0,0,V,
,,, мб неправильный коэффициент (Макс 12В)
Напр.ДУТ,VoltDUT,2101,((AA<8)+AB)/205,0,0,V,
Напр.дат.давл.хладагента,VoltACP,2101,((AC<8)+AD)/205,0,0,V,
Напр.дат.ТОЖ,VoltECT,2101,((A<8)+B)/205,0,5,V,
Датчик детонации,KnockSens,2101,((G<8)+H)/205,0,0,V,
,,,, УОЗы
УОЗ1,УОЗ1,2103,(192-A)/2.677,-30,72,deg,
,УОЗ2,УОЗ2,2103,(192-B)/2.677,-30,72,deg,
,УОЗ3,УОЗ3,2103,(192-C)/2.677,-30,72,deg,
,УОЗ4,УОЗ4,2103,(192-D)/2.677,-30,72,deg,
Требуемый УОЗ,треб УОЗ,2103,(G-64)/2.677,-30,72,deg,
Пробег,Mileage,2105,((AD<16)+(AE<8)+AF)/10,0,999999,km,
Счетчик включений зажигания,IgnCnt,2107,((N*256)+O),0,65535,,
,, Усредненое значение
Fuel Tank,FuelTankL,210b,(X-18)*2/255*45,0,45,l,
Fuel Tank%,FuelTank%,210b,(X-18)*2/255*100,0,100,%,
Бензонасос,FuelPump,210B,{A:0},0,1,0ff/On,
O2Heater,HeatO2S,210B,{B:0},0,1,0ff/On,
Режим ХХ,EngIdle,210B,{C:0},0,1,Off/on,
Отключение подачи топлива,InjOff,210B,{G:0},0,1,Off/on,
Полная нагрузка,FullLoad,210B,{H:0},0,1,0ff/On,
ДЗ закрыта,PSClose,210B,{I:0},0,1,0ff/On,
,Впускной коллектор переменной длины,TwinPort,210B,{Q:0},0,1,0ff/On,
Кондиционер,A/C,210B,{R:0},0,1,0ff/On,
Реле низкой скор.вент.охл-я,FanLow,210B,{S:0},0,1,0ff/On,
Реле высокой скор.вент.охл-я,FanHi,210B,{T:0},0,1,0ff/On,
,муфта гидротрансформатора АКПП,Clutch,210B,{U:0},0,1,0ff/On,
ABS левое переднее,ABS LF Speed,210B,AA,0,255,km/h,
,drive,drive,210C,{A:0},0,1,off/on,
Closed Loop,CL,210C,{D:0},0,1,off/on,
,RPM_avg,RPM_avg,210C,F*256+G,0,6000,rpm,
,Скорость3_raw,Speed3raw,210C,H,0,255,km/h,
,t ОЖ2,ECT2,210C,O/255*192-49,-50,140,C,
,t впуска2,IAT2,210C,P/255*192-49,-50,140,C,
Режим работы двигателя,EngState,210C,AF,0,5,,
,Режим работы двигателя,EngState2,210b,B,0,5,,
Требуемый ХХ,NeedIdleRPM,210D,(M<8)+N,500,1500,rpm,
ДЗ закрыта,notAccel,210D,{E:0},0,1,Off/on,
Время с запуска двигателя,EngRunTime,2117,((H<16)+(I<8)+J)/600,0,27961,min,
или если Serial не работает с ТВоут, то попробовать 2 ардуины связать по I2c или SPI. Одна выводит на дисплей, другая собирает параметры по к-лайн и отправляет их первой дуне, которая обслужвает дисплей
и Olivia, и ChevriletExplorer на основе имеюшихся данных расчитывают мгновенны расход на мое машине. Осталось только разобраться как они это делают! ))))
подключаешь эксплоер к машине. Параллельно цепляешь сниффер, (та же к-лайн ардуина только со скетчем сниффера), он много раз тут обсуждался ищи. Когда будет сниф, можно будет о чём то говорить. Расшаривается быстрее, без всяких документов. Очень часто описание протокола не соответствует дейтсвительности.
и Olivia, и ChevriletExplorer на основе имеюшихся данных расчитывают мгновенны расход на мое машине. Осталось только разобраться как они это делают! ))))
скорее всего это не диагностическая программа рассчитывает, а получает готовую цифру от ЭБУ в PIDe
MaksVV дружище, если обьявишся дай знать, оооооочень нужна твоя помощь.
Приветствую! говори
MaksVV такое дело. У меня начал выпендриватся тач, по пречине что изначально китайцы не поставили шлейф, я поставил, но суть не в этом. Хочу заменить другой экран, но.... проблема, что такие экраны как у меня был ( с широкой шиной пинов под мегу + гребенки по бокам, ниже фото) уже не суцествует в природе, есть только совместимы с мегой (которые имеют гребенку пинов по бокам, ниже фото). Купил такой, он не работает с UTFT и UTFTTouch библой, пытался в библах прописать пины тача и экрана, результат белый экран, а работает с скачать MCUFRIEND_kbv и скачать Adafruit-TouchScreen и эта библа понадобится скачать Adafruit GFX graphics , так как экран выдает ид ID=0x1581 то там вроде чип R61581. Думал отделатся малой кровью, но...., там фунции и имена отличаются. Я взял с этой библы пробу тача и вывод текста на экра и скрестил их, получил текст на экране и корды тача выдаваемые в порту. В библе mcufriend_kbv есть пример GLUE_Demo_480x320, там функции и имена как в UTFT, но он не работает. Чувствую еще тот гемор будет со скетчем. Задача переделать скетч под эти библы и не потерять функционал скетча. Я пробовал некоторые вещи типа замены myGLCD.print на tft.print но там функции отличаются вот и вываливается куча ошибок в компиляции. Я выложу вечером скетчи. Глянь как это можно реализовать, буду очень признателен.
P.S. Если решим эту проблему, выложу и под такие экраны, так как все смогут купить под мегу только совместимы, как купил я.
Был с такими пинами
купил с таким пинами
Нашел уже кое-что. в библе MCUFRIEND_kbv есть некий файл UTFTGLUE.h, он работает как переводчик между UTFT и Adafruit. В скетче по идеи ничего менять не нужно, НО ЕЩЕ НЕ ПРОБОВАЛ, завтра попробую. Если запустится останится разобратся с тачем, я заносил все параметры в скетч для подключения TouccScreen библы до тех пор, пока скетч не начал выдавать ошибки. вод скетч который подправил:
IDE 1.8.9 испльзую
По идеи нужно будет
39 закоментить, и в 8ми строках где myTouch правильно прописать
заработало но отображение корявое. ща буду капать.
и че как в итоге эти алгоритмы с расходами топлива и остатком до заправки? работают или далеки от правды?
Расходы нормально можно ориентироватся на длинных пробежкаках, на коротких так себе, по этому выставил средний 6.7 литров (много раз проверил и высчитал) и норм на коротких и на дальних.
поборол кривезну. осталось разобратся с шрифтом и тачем. вот скетч без тача
кстати я научился читать сообщения из kwp без всяких delay, из-за которых мы мучились. Можно оптимизировать эту часть, когда с экраном разберёшься.
почти разобрался c экраном, закончу кину скетч, давай оптимезируешь, с удовольствием приму :)
Блин второй день борюсь с отрисовкой и тачем. Выдернул меню из своего скетча, прописал тач, все работает. Вставлюю в основной скетчь строки для тачя, ЗАРАЗА НЕ РЕАГИРУЕТ. взял в скетче закоментил строку в лупе *receive ();, тач заработал но, отображение страноое вот
Выяснил что отрубает тачь(может не отрубает тач а просто все зависает потому что прорисовываются только заголовки и дата с временем но мигающих точек нет, а данные не прорисовываются и тач не работает, скорее всего зависает) сторока receive (); в воид луп,
а кривит изображение строки Temperature (); в воид сетуп и if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();} в воид луп
закоментив эти три сторки получаю гуд тачь и гуд прорисовка, единственное что присутствует видимость мигания обновления вывода данных, одн раз по времени и дате и три раза по данным, циклично, наверно потому что receive (); закоментирован в воид лупе.
скетч
копаю дальше. по ходу гдето есть конфликт
нашел кусок который все валит,он в начале void receive ()
Не могу понять в чем причина зависания. MaksVV помоги разобратся, ПЛИЗ
Все я сдаюсь. конфликт куска что выше, не могу понять, мерцание при обновлении не могу убрать, датчик температуры что ломает отображение так и не дошел. Может через неделю на свежую голову просмотрю.
не может соединиться со щитком приборов по какой либо причине. А там цикл while, т.е. в нем пытается соединиться со щитком , и если тщетно, то это будет бесконечно, соотвественно ничего другое в этот момент не работает, и ты видишь это как зависание. Смотри что в порту Serial при этом пишет. В скетче присутствует вывод туда отладки.
спасибо за подсказку, примерно это и подозревал что какойто цикл запроса зависает. в понедельник гляну и отпишусь. на этой недели нет времени.
MaksVV вообщем думаю нужно разбирать панель и на живую ставить экран и уже смотреть че да как.... С перового июля буду целый месяц иметь время, займусь этим. Будет видно на живую. расчитываю на твою помощь. если в отпуск не уедешь:).
Зачем разбирать , у тя ж в обд розетке к лайник приборки. Убери лишнее из скетча. Оставь только коннект с приборкой, посмотри будет ли подключение.
не макс. у меня все закрыто в одну коробку и коробка в панели. нужно снимать панель и вынемать весь бортовик с панели. а там все припаяно и приклеено клеевым пистолетом. только полная разборка и замена экрана. и тестить
ну ты же как то новый скетч тестил? куда ты его подключал? если ты просто новый экран тестил, не подключая к к-лайнам, то тогда все понятно. Возьми закоментируй эти циклы while, которые нужны для коннекта по к-лайн PCM и приборки, тогда можно и без коннектов к к-лайну потестить экран
да макс так и было. :) без ничего. просто тестил настраивал и подправлял отображение на экране. и все отлично работает. кроме этого нюанса. по этому и говорю только ставить и на живую. 1 июля буду разберать и менять. надеюсь все пройдет гладко
Привет viki13viki, вот нашел на Али дисплей 3,95" дюймов 320*480, вроде такой, какой Вы искали https://ru.aliexpress.com/item/3-8-3-95-320-480/32916041971.html с широкой колодкой пинов. После вставки шрифт постоянно меняется! )))
Потрясающе, что вы с MaksVV за 3 месяца смогли создать рабочий скетч для БК!!! Я сам давно хотел сделать для своей Нексии N150 БК, правда на PicBasicPro. Не хватило знаний, теперь делаю на Ардуино. Язык Си для меня гораздо сложнее, поэтому скетчи MaksVV очень помогли. Кстати, у моей машины тоже протокол ISO 14230 Fast Init 10400 и адреса запросов совпадают с Вашими! Так что для меня это подарок! Отдельное спасибо MaksVV за то, что он помог нескольким новичкам с программированием БК!
Спасибо за ссылку, но это не такой. Я уже справился с тем что приобрёл. А за программирование, да, это заслуга Макса.
Дак ты пробовал с новым экраном подключаться к машине? Т.е. уже всё заработало?
по поводу оптимизации скетча, в частности обмена по к-лайн (KWP) . Почитайте сообщение #1201. Там довольно важная информация по протоколу. А то у ТС когда мы скетч делали бортовика до этого ещё не дошли, и действовали как слепые котята, используя delay в сотни миллисек и борясь из-за этого с паразитными непонятными FF байтами, которых на шине по факту и не было, а был это результат некорректного формирования кадров из шины.
После бортовика ТС, я ещё способстовал проекту бортовика в этой теме Targitai на опель вектре. Дак вот там уже фигурируют скетчи обмена по к-лайн более продвинутые, с отсутствием delay в сотни миллисекунд, с проверкой контрольной суммы, и с автоматическим переподключением к PCM, если связь по какойто причине прервалась. например скетч #1321. Жаль что Targitai вроде как дело до конца так и не довёл. А ведь немного оставалось.
Нет еще не пробовал, только закончил с библиотеками и поправками отображения. 1 июля буду разберать. Посмотрю сообщения что ты пометил.
Спасибо, MaksVV, обязательно посмотрю. Сам пару лет назад научился писать код с параллельными процессами, но потом слетел винт-многое потерял, а главное потерял интерес. Так что в программировании меня отбросило далеко назад. ) Если все-таки доделаю БК, то выложу что получилось. Главное, чтобы мне жена не отдала свой Дастер, а то проект загнется, ведь там БК уже есть! )))))
viki13viki, подскажите, а Ваш БК считает мгновенный расход и расход топлива на 100 км? Если да, то подскажите по каким формулам?
БК для Нексии заработал на индикаторе пока в текстовом режиме на основе скетча №157. Также на основе этого скетча написал скетч с запросами поддерживаемых PIDов. Оказалось что из 196 PIDов 1-го сервиса на моей машине поддерживаются только 18! (1, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 17, 19, 20, 21, 28, 32 и 33). Нет ни Мафа, ни бортового напряжения. )))) Вот теперь вопрос как из этих данных рассчитать мгновенный расход и расход на 100 км? Кучу инета перелопатил. Нашел только как рассчитать Маф через Мап. Если есть у кого подходящие формулы-поделитесь, пож-та!
по всей видимости вы решили черпать информацию из стандартных обд2 PIDов. Но лучше её брать из PIDа протокола автопроизводителя. Обычно это один длинный PID, который содержит в себе все диагностические параметры сразу. Расшаривается этот пид с помощью снифа диагностической сессии диагностики и PCM. А также эмулятора PCM.
PS напишите какая нексия и какой PCM
Нексия N150 DOHC 1.8л 16-клапанная, двигатель Sirius 42. Не знаю что такое эмулятор PCM. Вообще у меня есть лог соединения БК на основе нетбука программой ChevroletExplorer, там запрос инициализации 81 11 F1 81 04.
и зачем нужен MAF ? вам же не воздух нужно рассчитать, а топливо.
вам нужно искать в параметрах расход топлива кг/ч, (с учетом плотности бензина посчитаете л/ч). Но иногда такой параметр отсутствует, тогда вам нужна цикловая подача топлива, обычно измеряется мл/такт (цикл), либо г/такт(цикл).
Обороты ДВС это рабочие циклы в минуту, переводим это в час получаем циклы в час. Перемножаем обороты и цикловую подачу, получаем тот же мл (или л)/ч. если в г/ч то с помощью плотности переводим в л/ч. и поделить на 2 , т.к. ДВС 4 тактный
далее с помощью скорости получаем л/100 км
стоит также попробовать PID остаток топлива в баке. запрос:
82 11 F1 01 2F B4
такой PID у меня не поддерживается, максимум 21 HEX (33 децимальный).
тогда вот ещё полезная инфа
в ответе на запрос 21 02 много параметров
у меня еще есть ELM327 и программы Torque и Olivia, попробую с ними достать эту инфу из ЭБУ. Ок, попробую с 21 02, спасибо!!!
в вот картинка с вашей программы , см. внизу нужные вам параметры уже рассчитаны. У вас такие не показывают?
Точно, надо снять скриншот!
Жаль что Targitai вроде как дело до конца так и не довёл. А ведь немного оставалось.
Ну это как посмотреть. Уперлись то мы в совместимость TV OUT и задержки...., Это только если пробовать со второй Ардуиной
а потом я еще и камеру китайскую снял, ибо задолбал квадрат малевича.
Хотя сейчас у меня уже 3 Ардуино валяются - Нано, Уно и Мега. Вот можно попробовать поиграться... Кажись, давал ссылку на этот же форум. Вроде получилось у товарища: http://arduino.ru/forum/programmirovanie/peredacha-dannykh-po-uart-pri-aktivnom-tvout
дак если камеры нет, может просто на графическом экране сделать как у ТС
Все таки я надеюсь на разборке какую то оригинальную найти и вместо китайской присобачить. В будущем.
А так смысл, если и так БК есть. Только ошибки читать - так это хоть лампочкой, хоть Опель Сканер.
или если Serial не работает с ТВоут, то попробовать 2 ардуины связать по I2c или SPI. Одна выводит на дисплей, другая собирает параметры по к-лайн и отправляет их первой дуне, которая обслужвает дисплей
Привет, MaksVV, у меня куча информации с ELM327 и ChevroletExplorer, но я не понимаю как тут вставить и сделать ссылку файлы txt и jpg.
текст вставлять как код, вверху на вкладке правой галка свернуть.
ответы на запросы 21 01:
а ссылки на картинки как сделать?
я так понимаю ответы на запрос 2101 содержат инфу по АЦП (напряжния) разных датчиков, если верить файлу #1379
читай песочницу первую тему
получилоь. Olivia через ELM. На хх
а эксплоер показывает расход?
и Olivia, и ChevriletExplorer на основе имеюшихся данных расчитывают мгновенны расход на мое машине. Осталось только разобраться как они это делают! ))))
По поводу запроса 21 01. В Вазовском документе 14230-3R.DOC по-другому расписаны байты ответа на этот запрос. Буду искать американский документ
подключаешь эксплоер к машине. Параллельно цепляешь сниффер, (та же к-лайн ардуина только со скетчем сниффера), он много раз тут обсуждался ищи. Когда будет сниф, можно будет о чём то говорить. Расшаривается быстрее, без всяких документов. Очень часто описание протокола не соответствует дейтсвительности.
и Olivia, и ChevriletExplorer на основе имеюшихся данных расчитывают мгновенны расход на мое машине. Осталось только разобраться как они это делают! ))))
скорее всего это не диагностическая программа рассчитывает, а получает готовую цифру от ЭБУ в PIDe