Попробовал это не то.А вот когда пробовал удалять конвертацию из галлонов в литры и наоборот, чтобы совсем убрать СТРОКА 2679 и так далее .Вместо -$1,325+ получилось -10,0какой то символ+ .Где то здесь наверное нужно изменять.GasConst 3355 это я понял для расчёта расхода топлива. Ещё такой вопрос,здесь контрастность меняется по шим сигналу.Где в коде можно увеличить частоту ,чтобы мерцание было меньше.Спасибо.
я вроде нашел косяк. Для того, чтобы данные на экран обновлялись только при их изменении, ты ввёл переменные с постфиксом _last
Дак вот в том числе и для переменной Fuel ты сделал Fuel_last для такого вывода на экран.
А переменная Fuel_last у нас уже была и использовалась в бортовике для расчёта среднего расхода и расстояния до заправки. А при выводе на экран ты эту переменную портишь, поэтому все расчёты в гавно.
исправил
//------------все для связи по K-line (тут настраиваем UARTы к-лайников, адреса блоков, скорость инита и отладку)
#include <SoftwareSerial.h>
#define TX_PCM 13
SoftwareSerial K_LINE_PCM (12, TX_PCM); //RХ,TХ //UART на котором висит K_line к PCM
#define K_LINE_GAUGE Serial2 //UART на котором висит K_line к приборке
#define TX_gauge 16 //TX UARTa на котором висит K_line к приборке
#define PCM_address 0x11 // адрес PCM
#define DIAG_address 0xF1 // адрес диагностики
const byte BAUD=200; // init baudrate - скорость инита при подключении к приборке
const byte addressGUAGE = 0xB8;// init GAUGE address - адрес щитка приборов при ините (установке связи)
#define debugPCM // раскоментировать эту строку для отладки в Serial порту обмена с PCM
//#define debugGAUGE // раскоментировать эту строку для отладки в Serial порту обмена co щитком приборов
//#define debugTRIP // раскоментировать эту строку для отладки в Serial порту данных бортовика
uint32_t curmillis = 0; // снимок текущего времени
//------------------------------------------переменные для организации протокола связи с PCM
uint32_t prevRequest = 0; // таймер периодических запосов на PCM
uint16_t RequestPeriod = 3500; // периодичность запросов на PCM
byte header = 0; // состояние заголовка
bool NOanswer_timer = 0; // таймер контроля неответов от ЭБУ после подачи запросов
uint32_t prev_NOanswer=0; // таймер контроля неответов от ЭБУ после подачи запросов
// возможные варианты запросов на ЭБУ:
enum REQUEST {INIT, PID, DTCERASE, DTCREAD, PRESENT,};
#ifdef debugPCM
// текстовки запросов для отладки
char* textRequest[] = {"INIT", "PID_2101", "DTC_ERASE", "DTC_READ", "PRESENT",} ;
#endif
// сами запросы
byte PCM_Message_TX[][5] = {
{1, 0x81, 0,0,0}, // запрос инициализации
{2, 0x21,0x01, 0,0}, // запрос пид 2101
{3, 0x14,0xFF,0x00, 0}, // запрос на стирание ошибок
{4, 0x18,0x00,0xFF,0x00 }, // запрос на чтение ошибок
{1, 0x3E, 0,0,0}, // запрос присутствия
};
byte request = INIT; // переменная, показывающая какой запрос будем делать
static byte headerGAUGE = 0; // состояние заголовка сообщений щитка приборов
const byte bufsize = 150; // размер буфера принятого сообщения
byte MessageRx_PCM [bufsize] = {0}; // буфер принятого сообщения
//-------------------------------------------переменные бортовика
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 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
int IntTemp = 0; //Температура улицы
//все что касается топлива
float Fuel = 0; //остаток топлива
float Fuel2 = 0; float Fuel2_last = 1; //остаток мгновенного топлива байт 16 , датчика в баке
int FuelIGN = 0; // количество топлива в баке на момент включения зажигания
float fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
float FuelTrip = 0; float FuelTrip_last = 1; // количество литров топлива, израсходованное за один цикл включения зажигания
//все что касается километража
float kmAge = 0; //пробег, полученный со щитка приборов
int kmAgeIGN = 0; //пробег который был в момент включения зажигания
int kmAge_last = 0; // для формул
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
float kmTrip = 0; float kmTrip_last = 1; //пробег за один цикл включения зажигания
const int kmL = 10; // интервал, через который будет происходить обновление среднего расхода на 100км
int km = 0; // переменная для расчетов
const int kmeeprom = 15; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING = 0; int kmREFUELING_last = 1; // пробег до заправки на остатке топлива
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
//----------------------------------------------для экрана
#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>
//#include "Fonts/Chosence_Bold16pt7b.h";
#define MINPRESSURE 200
#define MAXPRESSURE 1000
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
UTFTGLUE myGLCD(0x1581,A2,A1,A3,A4,A0); //all dummy args
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; int h_last = 1;
float t; int t_last = 1;
bool Dvoet = 0;
bool reNew = 0;
#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0xF800
#define GREEN 0x07E0
//--------------------------------------датчики t
byte DSaddress[] = {0x28, 0xFF, 0xA6, 0x19, 0xA8, 0x15, 0x01, 0xD2};
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 26
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#include <OneWire.h>
#define ONE_WIRE_BUS 22
OneWire ds(ONE_WIRE_BUS);
void setup() {
uint16_t ID = myGLCD.readID();
if (ID == 0xD3D3) ID = 0x1581; // write-only shield
myGLCD.begin(ID);
myGLCD.InitLCD(3);
myGLCD.clrScr();
myGLCD.setTextSize(2);
//myGLCD.setFont(&Chosence_Bold16pt7b);
Wire.begin();
rtc.begin();
dht.begin();
//загрузка стартовой страницы
currentPage = '0';
drawHomeScreen();
//подсчет среднеарифметического усредненного расхода
int summ=0;
for (int i = 0; i < 11; i++) summ += EEPROM.read(i);
L100SR_TFT = summ / 110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить времая и дату, залить в ардуино. в скетче закоментировать
// обратно и залить еще раз, иначе каждый раз будет по новой выствлятся это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2019, 7, 2, 10, 48, 0));
#if defined debugPCM or defined debugGAUGE or defined debugTRIP
Serial.begin(115200);
#endif
K_LINE_PCM.begin(10400);
pinMode(TX_PCM, OUTPUT);
}
void loop()
{
curmillis = millis(); // снимок текущего времени
if (curmillis - prevRequest > RequestPeriod && header == 0 )
{
if (request == INIT) fastinit(); // при необходимости делаем переподключение к PCM
else {sendMessagePCM(request); // отправляем на PCM текущий запрос
if (request == PID) RequestPeriod = 600;
if (request == DTCERASE || request == DTCREAD) RequestPeriod = 2500;}
prevRequest = curmillis;
}
receivePCM (); // приём сообщений от PCM
receiveGAUGE (); // приём сообщений от щитка приборов
if (header == 0 && headerGAUGE == 0) {Menu ();}
if (curmillis - prevWatch > 4000) { Watch (); prevWatch = curmillis; Trip (); h = dht.readHumidity(); t = dht.readTemperature();Temperature ();}
//if (curmillis - prevDvoet > 500) { if (!Dvoet) {myGLCD.setTextColor(WHITE); } else {myGLCD.setTextColor(BLACK); } myGLCD.print(":", 290, 5); prevDvoet = curmillis; Dvoet=!Dvoet;}
if (millis() - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 280, 5);} else {myGLCD.print(" ", 290, 5);} prevDvoet = millis(); Dvoet=!Dvoet;}
}// end loop
void fastinit() {
digitalWrite (TX_PCM, HIGH); // bus idle
delay(1500);
digitalWrite (TX_PCM, LOW); // first part fastinit (25 ms LOW)
delay(25);
digitalWrite (TX_PCM, HIGH); // second part fastinit (25 ms HIGH)
delay(25);
K_LINE_PCM.begin(10400);
sendMessagePCM(INIT); // send start communication message
}
void receivePCM () {
static uint32_t prevRESETheader=0; // таймер сброса сообщения, если данные оборвались посередине сообщения
static bool RESETheader_timer; // таймер сброса сообщения, если данные оборвались посередине сообщения
static byte noanswers = 0; // количество подряд неответов от ЭБУ
static byte message_size = 0; // размер тела сообщения
static byte j = 3; // инкремент
static byte n = 3; // количество старт байт
static byte crc =0; // байт контрольной суммы
if (K_LINE_PCM.available() ){
// первый старт байт
if (header == 0){ MessageRx_PCM[0]=K_LINE_PCM.read();
if (MessageRx_PCM[0]!=0xFF && bitRead (MessageRx_PCM[0],7)){header = 1; RESETheader_timer = 1; prevRESETheader = curmillis;
#ifdef debugPCM
Serial.print (F("Receive PCM: ")); printDebugRX(MessageRx_PCM[0]);
#endif
}
}
// второй старт байт
else if (header == 1){ MessageRx_PCM[1]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX (MessageRx_PCM[1]);
#endif
if (MessageRx_PCM[1]==DIAG_address){ header = 2;}
else {
#ifdef debugPCM
Serial.println(F(" PCM Message fail address"));
#endif
header = 0; RESETheader_timer = 0;}}
// третий старт байт
else if (header == 2){
MessageRx_PCM[2]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX (MessageRx_PCM[2]);
#endif
if (MessageRx_PCM[2]==PCM_address){ message_size = MessageRx_PCM[0]; prevRESETheader = curmillis;
if (MessageRx_PCM[0] !=0x80) {header = 4; bitWrite (message_size, 7 , 0);j=3;n=3;}
else {header = 3; j=4;n=4;}
if (message_size > bufsize) message_size = bufsize; crc = 0;}
else {header = 0;
#ifdef debugPCM
Serial.println(F("PCM Message fail address"));
#endif
RESETheader_timer = 0;}
}
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
prevRESETheader = curmillis;
MessageRx_PCM[3]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX(MessageRx_PCM[3]);
#endif
message_size = MessageRx_PCM[3];
if (message_size > bufsize) message_size = bufsize;
crc = 0; header = 4;
}
// пишем тело сообщения
else if (header == 4 && j< message_size+n+1) {
MessageRx_PCM[j] = K_LINE_PCM.read(); prevRESETheader = curmillis;
if (j<message_size+n) crc+= MessageRx_PCM[j]; // подсчёт КС
if (j==message_size+n) header = 5;
#ifdef debugPCM
printDebugRX(MessageRx_PCM[j]);
#endif
j++; }
}
// сообщение приняли, действуем
if (header == 5) {
#ifdef debugPCM
Serial.println();
#endif
NOanswer_timer = 0; noanswers = 0; // сбрасываем таймер контроля неответов
for(byte i = 0; i<n; i++) crc+=MessageRx_PCM[i]; // прибавляем к контрольной сумме старт байты
// если контрольная сумма верна:
if ( crc == MessageRx_PCM[message_size+n])
{
#ifdef debugPCM
Serial.print (F("Received message is OK! Checksum is correct!")); Serial.print (F(" ")); Serial.println (millis()); // Если КС совпала, тут чёнибудь нужное делаем
printDebugRX_CSgood(n);
#endif
if (MessageRx_PCM[n]==0xC1 && MessageRx_PCM[n+1]==0x6B && MessageRx_PCM[n+2]==0x8F) {
if (currentPage!=3) {request = PID; RequestPeriod = 70;} else request = PRESENT, RequestPeriod = 4000; prevRequest = curmillis; // receive good INIT
}
else if (MessageRx_PCM[n]==0x58) Troublecodes (n); // DTC
else if (MessageRx_PCM[n]==0x54 && MessageRx_PCM[n+1]==0xFF && MessageRx_PCM[n+2]==0x00){ request = PRESENT; RequestPeriod = 4000; prevRequest = curmillis;} // DTC are cleared
else if (MessageRx_PCM[n]==0x61 && MessageRx_PCM[n+1]==0x01) {dataVars(n) ; RequestPeriod = 70; prevRequest = curmillis; } // receive DataStream
}
// если контрольная сумма не совпала:
#ifdef debugPCM
else Serial.println("CRC fail!!!" );
#endif
message_size = 0; header=0; RESETheader_timer = 0; j=3; crc = 0;
}
// таймер сброса целостности сообщения (если данные оборвались посередине сообщения)
if (RESETheader_timer && curmillis - prevRESETheader > 200) {
#ifdef debugPCM
Serial.println(F("Message fail timeout"));
#endif
RESETheader_timer = 0; header = 0;}
// если нет ответа после запроса: +1 к счетчику неответов. Если накопилось 6 и более: делаем реинит.
if (request!=INIT && NOanswer_timer && curmillis - prev_NOanswer > RequestPeriod - RequestPeriod/10)
{
NOanswer_timer = 0; noanswers++;
if (noanswers>=6) { noanswers = 0; request = INIT; RequestPeriod = 3500;}
}
}// end receivePCM
void Troublecodes (const byte &n)
{
if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]==0x00){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 180, 145);
}
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]>0){
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx_PCM[n+8-7]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx_PCM[n+11-7+(i*3)],6) && bitRead(MessageRx_PCM[n+11-7+(i*3)],7)){ myGLCD.setTextColor(GREEN, BLACK);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx_PCM[n+11-7+(i*3)],7) && bitRead(MessageRx_PCM[n+11-7+(i*3)],6)) { myGLCD.setTextColor(RED, BLACK);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && !bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && !bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx_PCM[n+9-7+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx_PCM[n+9-7+(i*3)]<=0x0F&&MessageRx_PCM[n+9-7+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}
if (nolA)myGLCD.print(String (MessageRx_PCM[n+9-7+(i*3)],HEX), 246, (75+y));
else myGLCD.print(String (MessageRx_PCM[n+9-7+(i*3)],HEX), 230, (75+y));
if (MessageRx_PCM[n+10-7+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx_PCM[n+10-7+(i*3)]<=0x0F&&MessageRx_PCM[n+10-7+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;}
if (nolB)myGLCD.print(String (MessageRx_PCM[n+10-7+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx_PCM[n+10-7+(i*3)],HEX), 262, (75+y));}}
request = PRESENT; RequestPeriod = 4000; prevRequest = curmillis;
}
void dataVars(const byte &n)
{
static float L100M_last = 1; //расход на 100 км измеренный за поездку
static float L100_last = 1; //мгновенный расход литров на 100км
static float LHor_last = 1; //мгновенный расход топлива литров в час
static float L100SR_TFT_last = 1; // самый средний из расходов на 100км, он выводится на экран
static int MAF_last = 1; //26,27 байты Sensor de flujo de aire en masa
static float BoostPres_last = 1; //28,29 байты Presión de refuerzo
static int RPM_last = 1; //32,33 байты Velocidad del motor
static int EGRmg_last = 1; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
static float BoostPresCom_last = 1;//38,39 байты Comando de presión de refuerzo
static int Speed_last = 1; //44,45 байты Velocidad del vehículo
static float DesaInjQua_last = 1; //50,51 байты Cantidad de inyección deseada
static float InjQua_last = 1; //52,53 байты Cantidad de la inyección
static float StaDaliv_last = 1; //54,55 байты Inicio de la entrega
static int PumpRPM_last = 1; //56,57 байты Velocidad de la bomba
static float EGRPul_last = 1; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
static float SolenPul_last = 1; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
static float SolenPre_last = 1; //70,71 байты Relación de impulsos Presión Electroválvula de presión
static float DesInj_last = 1; //72,73 байты Inyección deseada Inicio
static float ActInj_last = 1; //16,17 байты Inicio de la inyección real
static int TempAir_last = 1; //74,75 байты Temperatura del aire de admisión
static int Temp_last = 1; //14,15 байты Temperatura del refrigerante
static int TempOil_last = 1; //18,19 байты Temperatura del aceite del motor
static int TempFuel_last = 1; //58,59 байты Temperatura del combustible
static int IntTemp_last = 1; //Температура улицы
static float Fuel_last = 1; //уровень топлива в баке
//Barom = MessageRx_PCM[39];
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
L100 = (float)LHor*100.0/(float)Speed;
MAF = ((MessageRx_PCM[n+22]*256)+MessageRx_PCM[n+23])/10;
BoostPres = ((MessageRx_PCM[n+24]*256)+MessageRx_PCM[n+25])/1000.0;
RPM = (MessageRx_PCM[n+35-7]*256)+MessageRx_PCM[n+36-7];
EGRmg = ((MessageRx_PCM[n+37-7]*256)+MessageRx_PCM[n+38-7])/10.0;
BoostPresCom = ((MessageRx_PCM[n+41-7]*256)+MessageRx_PCM[n+42-7])/1000.0;
Speed = ((MessageRx_PCM[n+47-7]*256)+MessageRx_PCM[n+48-7])/100;
DesaInjQua = ((MessageRx_PCM[n+53-7]*256)+MessageRx_PCM[n+54-7])/100.0;
InjQua = ((MessageRx_PCM[n+55-7]*256)+MessageRx_PCM[n+56-7])/100.0;
StaDaliv = ((MessageRx_PCM[n+57-7]*256)+MessageRx_PCM[n+58-7])/100.0;
PumpRPM = (MessageRx_PCM[n+59-7]*256)+MessageRx_PCM[n+60-7];
EGRPul = ((MessageRx_PCM[n+65-7]*256)+MessageRx_PCM[n+66-7])/100.0;
SolenPul = ((MessageRx_PCM[n+67-7]*256)+MessageRx_PCM[n+68-7])/100.0;
SolenPre = ((MessageRx_PCM[n+73-7]*256)+MessageRx_PCM[n+74-7])/100.0;
DesInj = ((MessageRx_PCM[n+75-7]*3)+(MessageRx_PCM[n+76-7])/100.0)+0.3;
ActInj = ((MessageRx_PCM[n+19-7]*3)+(MessageRx_PCM[n+20-7])/100.0)+0.3;
//TempAir = ((MessageRx_PCM[n+77-7]*26)-278)+MessageRx_PCM[n+78-7]/10.0;
//Temp = ((MessageRx_PCM[n+17-7]*26)-278)+MessageRx_PCM[n+18-7]/10.0;
//TempOil = ((MessageRx_PCM[n+21-7]*26)-278)+MessageRx_PCM[n+22-7]/10.0;
//TempFuel = ((MessageRx_PCM[n+61-7]*26)-278)+MessageRx_PCM[n+62-7]/10.0;
//ниже идут расчетные формулы более точные чем те что закоментированы выше
int A = 0;
if (MessageRx_PCM[n+77-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+77-7]==0x0B || MessageRx_PCM[n+77-7]==0x0C) A = 278;
if (MessageRx_PCM[n+77-7]>=0x0D) A = 279;
double B = MessageRx_PCM[n+78-7]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx_PCM[n+77-7]*26)-A)+cel;
if (MessageRx_PCM[n+17-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+17-7]==0x0B || MessageRx_PCM[n+17-7]==0x0C) A = 278;
if (MessageRx_PCM[n+17-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+18-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx_PCM[n+17-7]*26)-A)+cel;
if (MessageRx_PCM[n+21-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+21-7]==0x0B || MessageRx_PCM[n+21-7]==0x0C) A = 278;
if (MessageRx_PCM[n+21-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+22-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx_PCM[n+21-7]*26)-A)+cel;
if (MessageRx_PCM[n+61-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+61-7]==0x0B || MessageRx_PCM[n+61-7]==0x0C) A = 278;
if (MessageRx_PCM[n+61-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+62-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx_PCM[n+61-7]*26)-A)+cel;
//----------------------------------------------------------
//страниц HOME
//----------------------------------------------------------
//myGLCD.setBackColor(RED);
myGLCD.setTextColor(WHITE, BLACK);
//myGLCD.setBackColor(RED);
if ((Speed != Speed_last) || reNew) {myGLCD.printNumI(Speed, 360, 7, 3); Speed_last=Speed;}
if (currentPage == '0') {
if ((LHor != LHor_last) || reNew) {myGLCD.printNumF(LHor, 1, 75, 40, '.',4); LHor_last=LHor;}
if ((L100 != L100_last) || reNew) {myGLCD.printNumF(L100, 1, 225, 40,'.',4 ); L100_last=L100;}
if ((L100M != L100M_last) || reNew) {myGLCD.printNumF(L100M, 1, 75, 75,'.',4 ); L100M_last=L100M;}
if ((L100SR_TFT != L100SR_TFT_last) || reNew) {myGLCD.printNumF(L100SR_TFT, 1, 225, 75,'.',4 ); L100SR_TFT_last=L100SR_TFT;}
if ((kmREFUELING != kmREFUELING_last) || reNew) {myGLCD.printNumI(kmREFUELING, 90, 110,3 ); kmREFUELING_last=kmREFUELING;}
//if (Fuel<53)
if ((Fuel != Fuel_last) || reNew) {myGLCD.printNumF(Fuel, 1, 225, 110,'.',4); Fuel_last=Fuel;}
//else myGLCD.print("MAX", 210, 110);
if ((kmTrip != kmTrip_last) || reNew) {myGLCD.printNumF(kmTrip, 1, 60, 145,'.',5); kmTrip_last=kmTrip;}
if ((FuelTrip != FuelTrip_last) || reNew) {myGLCD.printNumF(FuelTrip, 1, 210, 145,'.',5); FuelTrip_last=FuelTrip;}
if ((PumpRPM != PumpRPM_last) || reNew) {myGLCD.printNumI(PumpRPM, 230, 180,4); PumpRPM_last=PumpRPM;}
if ((RPM != RPM_last) || reNew) {myGLCD.printNumI(RPM, 230, 215,4); RPM_last=RPM;}
if ((Fuel2 != Fuel2_last) || reNew) {myGLCD.printNumF(Fuel2, 1, 10, 215,'.',4); Fuel2_last=Fuel2;}
if ((Temp != Temp_last) || reNew) {myGLCD.printNumI(Temp, 415, 40, 3); Temp_last=Temp;}
if ((TempOil != TempOil_last) || reNew) {myGLCD.printNumI(TempOil, 415, 75, 3); TempOil_last=TempOil;}
if ((TempFuel != TempFuel_last) || reNew) {myGLCD.printNumI(TempFuel, 415, 110,3); TempFuel_last=TempFuel;}
if ((IntTemp != IntTemp_last) || reNew) {myGLCD.printNumI(IntTemp, 415, 145 , 3); IntTemp_last=IntTemp;}
if ((t != t_last) || reNew) {myGLCD.printNumI(t, 415, 180, 3); t_last=t;}
if ((TempAir != TempAir_last) || reNew) {myGLCD.printNumI(TempAir, 415, 215, 3); TempAir_last=TempAir;}
reNew = 0;
}
//----------------------------------------------------------
//страниц INF1
//----------------------------------------------------------
if (currentPage == '1') {
if ((StaDaliv != StaDaliv_last) || reNew) {myGLCD.printNumF(StaDaliv,1, 385, 40,'.', 4); StaDaliv_last=StaDaliv;}
if ((DesInj != DesInj_last) || reNew) {myGLCD.printNumF(DesInj,1, 385, 75, '.', 4); DesInj_last=DesInj;}
if ((ActInj != ActInj_last) || reNew) {myGLCD.printNumF(ActInj,1, 385, 110,'.', 4); ActInj_last=ActInj;}
if ((DesaInjQua != DesaInjQua_last) || reNew) {myGLCD.printNumF(DesaInjQua,1, 385, 145,'.', 4);DesaInjQua_last=DesaInjQua;}
if ((InjQua != InjQua_last) || reNew) {myGLCD.printNumF(InjQua,1, 385, 180,'.', 4); InjQua_last=InjQua;}
if ((MAF != MAF_last) || reNew) {myGLCD.printNumI(MAF, 170, 215, 4); MAF_last=MAF;}
if ((h != h_last) || reNew) {myGLCD.printNumF(h, 1, 430, 215, 3); h_last=h;}
reNew = 0;
}
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
if ((BoostPres != BoostPres_last) || reNew) {myGLCD.printNumF(BoostPres,1, 400, 40,'.', 4); BoostPres_last=BoostPres;}
if ((BoostPresCom != BoostPresCom_last) || reNew) {myGLCD.printNumF(BoostPresCom,1, 400, 75,'.', 4); BoostPresCom_last=BoostPresCom;}
if ((EGRmg != EGRmg_last) || reNew) {myGLCD.printNumI(EGRmg, 400, 110, 4); EGRmg_last=EGRmg;}
if ((EGRPul != EGRPul_last) || reNew) {myGLCD.printNumF(EGRPul,1, 400, 145,'.', 4); EGRPul_last=EGRPul;}
if ((SolenPul != SolenPul_last) || reNew) {myGLCD.printNumF(SolenPul, 1, 400, 180,'.', 4); SolenPul_last=SolenPul;}
if ((SolenPre != SolenPre_last) || reNew) {myGLCD.printNumF(SolenPre, 0, 400, 215,'.', 4); SolenPre_last=SolenPre;}
reNew = 0;
}
//reNew = 0;
}
void sendMessagePCM(const byte &command)
{
#ifdef debugPCM
Serial.print (F("Send request ")); Serial.print (textRequest[command]); Serial.print (F(" to PCM ")); Serial.println (millis());
#endif
if (command != INIT) {NOanswer_timer = 1; prev_NOanswer = curmillis;} //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов
byte size = PCM_Message_TX[command][0];
const byte siZe = size+4;
byte Mes[siZe];
byte Checksum = 0;
for(byte i=0; i<siZe; i++) {
if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
if (i==1) Mes[i] = PCM_address;
if (i==2) Mes[i] = DIAG_address;
if (i==3) {for (byte t=1; t<size+1; t++ ) {
Mes[i]=PCM_Message_TX [command][t];
Checksum+=Mes[i] ;
K_LINE_PCM.write (Mes[i]);
if (command == INIT) delay (5); else delay (1);
K_LINE_PCM.read();
i++;}}
if (i!=siZe-1) Checksum+=Mes[i];
else Mes[i] = Checksum;
K_LINE_PCM.write (Mes[i]);
if (command == INIT) delay (5); else delay (1);
K_LINE_PCM.read();
}
}// end sendMessagePCM
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;
// тут считаем среднеарифметический усредненного расхода из ячеек еепром
int summ = 0;
for (int i = 0; i < 11; i++) summ += EEPROM.read(i);
L100SR_TFT = summ / 110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 25;}
// ниже цикл считает расход топлива за пробег, указанный в переменной 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); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
byte 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);
#ifdef debugTRIP
Serial.println (" I am heer: if (kmTrip-km>kmL) {} ");
Serial.print (" L100SR = "); Serial.print (L100SR) ; Serial.println (" L/100km");
Serial.print (" kmREFUELING = "); Serial.print (kmREFUELING) ; Serial.println (" km");
#endif
}
#ifdef debugTRIP
Serial.print (" FuelTrip = "); Serial.print (FuelTrip); Serial.println (" L");
Serial.print (" kmTrip = "); Serial.print (kmTrip); Serial.println (" km");
Serial.print (" L100SR_TFT = "); Serial.print (L100SR_TFT); Serial.println (" L/100km");
#endif
}}
void receiveGAUGE () {
static uint32_t prevRESETheaderGAUGE=0; // таймер сброса сообщения, если данные оборвались посередине сообщения
static bool RESETheader_timerGAUGE; // таймер сброса сообщения, если данные оборвались посередине сообщения
static uint32_t prevNoconnect = 0; // таймер периодической проверки наличия связи со щитком приборов
static byte NoconnectsGAUGE = 0 ; // счетчик неответов от щитка приборов
static byte message_sizeGAUGE = 0; // размер тела сообщения
static byte jGAUGE = 3; // инкремент
static byte nGAUGE = 3; // количество старт байт
static int ChecksumGAUGE =0; // байт контрольной суммы
static byte InitGauge = 0; // автомат состояния инита щитка приборов
const byte bufsizeG = 100; // размер буфера принятого сообщения
static byte MessageRx_GAUGE [bufsizeG] = {0}; // буфер принятого сообщения
byte PIDgauge[] = {0x02,0x11,0x00,0x13}; // запрос параметоров щитка приборов
if (K_LINE_GAUGE.available() ){
// первый старт байт
if (headerGAUGE == 0){ MessageRx_GAUGE[0]=K_LINE_GAUGE.read();
if ((InitGauge ==1 && MessageRx_GAUGE[0]==0x55) || (InitGauge ==2 && MessageRx_GAUGE[0]!=0xFF && MessageRx_GAUGE[0]!=0x7F)
|| (InitGauge ==3 && MessageRx_GAUGE[0]==0x23)
)
{headerGAUGE = 1; RESETheader_timerGAUGE = 1; prevRESETheaderGAUGE = curmillis;
#ifdef debugGAUGE
Serial.print (F("Receive GAUGE: ")); printDebugRX(MessageRx_GAUGE[0]);
#endif
}
}
// второй старт байт
else if (headerGAUGE == 1){ MessageRx_GAUGE[1]=K_LINE_GAUGE.read();
#ifdef debugGAUGE
printDebugRX (MessageRx_GAUGE[1]);
#endif
if ( (InitGauge ==1 && MessageRx_GAUGE[1]==0x52) || (InitGauge ==2 && (MessageRx_GAUGE[1]==0xA0 || MessageRx_GAUGE[1]==0xF0))
|| (InitGauge == 3 && MessageRx_GAUGE[1]==0xA1)){ headerGAUGE = 2;}
else {
#ifdef debugGAUGE
Serial.println(F(" GAUGE Message fail address"));
#endif
headerGAUGE = 0; RESETheader_timerGAUGE = 0;}}
// третий старт байт
else if (headerGAUGE == 2){
MessageRx_GAUGE[2]=K_LINE_GAUGE.read();
#ifdef debugGAUGE
printDebugRX (MessageRx_GAUGE[2]);
#endif
if ((InitGauge ==2 && (MessageRx_GAUGE[2]==0x48 || MessageRx_GAUGE[2]==0x55 || MessageRx_GAUGE[2]==0xAA)) || (InitGauge == 3 && MessageRx_GAUGE[2]==0x04)){ message_sizeGAUGE = MessageRx_GAUGE[0]-2; prevRESETheaderGAUGE = curmillis;
headerGAUGE = 4; jGAUGE=3; nGAUGE=3;
if (message_sizeGAUGE > bufsizeG) message_sizeGAUGE = bufsizeG; ChecksumGAUGE = 0;}
else if (InitGauge ==1 && MessageRx_GAUGE[2]==0x80) {InitGauge = 2; K_LINE_GAUGE.write(0x7F); delay (2); K_LINE_GAUGE.read(); headerGAUGE = 0; RESETheader_timerGAUGE = 0;
#ifdef debugGAUGE
Serial.println ("Gauge INIT is good!");
#endif
}
else {headerGAUGE = 0;
#ifdef debugGAUGE
Serial.println(F("GAUGE Message fail address"));
#endif
RESETheader_timerGAUGE = 0;}
}
// пишем тело сообщения
else if (headerGAUGE == 4 && jGAUGE< message_sizeGAUGE+nGAUGE+1) {
MessageRx_GAUGE[jGAUGE] = K_LINE_GAUGE.read(); prevRESETheaderGAUGE = curmillis;
if (jGAUGE<message_sizeGAUGE+nGAUGE-1) ChecksumGAUGE+= MessageRx_GAUGE[jGAUGE]; // подсчёт КС
if (jGAUGE==message_sizeGAUGE+nGAUGE) headerGAUGE = 5;
#ifdef debugGAUGE
printDebugRX(MessageRx_GAUGE[jGAUGE]);
#endif
jGAUGE++; }
}
// сообщение приняли, действуем
if (headerGAUGE == 5) {
#ifdef debugGAUGE
Serial.println();
#endif
for(byte i = 0; i<nGAUGE; i++) ChecksumGAUGE+=MessageRx_GAUGE[i]; // прибавляем к контрольной сумме старт байты
int ChecksumG = ( ( unsigned int )MessageRx_GAUGE[message_sizeGAUGE+nGAUGE-1] << 8 ) | MessageRx_GAUGE[message_sizeGAUGE+nGAUGE]; // парсинг контрольной суммы из 2 последних байт
// если контрольная сумма верна:
if ( ChecksumGAUGE == ChecksumG)
{ NoconnectsGAUGE = 0; // сбрасываем на 0 отсутствие связи с панелью
#ifdef debugGAUGE
Serial.print (F("Received message is OK! Checksum is correct!")); Serial.print (F(" ")); Serial.println (millis()); // Если КС совпала, тут чёнибудь нужное делаем
#endif
if (MessageRx_GAUGE[1]== 0xA0 && MessageRx_GAUGE[2]== 0x48) {
#ifdef debugGAUGE
Serial.println ("ID panel receive! Send request PIDGauge");
#endif
InitGauge = 3;
for (byte i=0; i<sizeof(PIDgauge); i++) { K_LINE_GAUGE.write (PIDgauge[i]); delay (1); K_LINE_GAUGE.read();}
}
if (MessageRx_GAUGE[1]== 0xF0 && (MessageRx_GAUGE[2]== 0xAA || MessageRx_GAUGE[2]== 0x55)) {
#ifdef debugGAUGE
Serial.println ("receive present from Gauge. I send PID to Gauge");
#endif
InitGauge = 3;
for (byte i=0; i<sizeof(PIDgauge); i++) { K_LINE_GAUGE.write (PIDgauge[i]); delay (1); K_LINE_GAUGE.read();}
}
if (MessageRx_GAUGE[1]== 0xA1 && MessageRx_GAUGE[2]== 0x04) {
#ifdef debugGAUGE
Serial.println (" receive Datastream Gauge!");
#endif
Fuel2 = MessageRx_GAUGE[nGAUGE + 16]/2.0;
if (!flagFuelIGN) { Fuel = MessageRx_GAUGE[nGAUGE + 16]/2.0; kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;} //стартовая запись литров в баке для подсчета затраченных литро
else Fuel = MessageRx_GAUGE[nGAUGE + 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 = (MessageRx_GAUGE[nGAUGE + 23]+(MessageRx_GAUGE[nGAUGE + 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;}}
#ifdef debugTRIP
Serial.print (" Fuel = "); Serial.print (Fuel); Serial.println (" L");
Serial.print (" kmAge = "); Serial.print (kmAge); Serial.println (" km");
#endif
}
}
// если контрольная сумма не совпала:
#ifdef debugGAUGE
else Serial.println("CRC fail!!!" );
#endif
message_sizeGAUGE = 0; headerGAUGE=0; RESETheader_timerGAUGE = 0; jGAUGE=3; ChecksumGAUGE = 0;
}
// таймер сброса целостности сообщения (если данные оборвались посередине сообщения)
if (RESETheader_timerGAUGE && curmillis - prevRESETheaderGAUGE > 300) {
#ifdef debugGAUGE
Serial.println(F("Message fail timeout"));
#endif
RESETheader_timerGAUGE = 0; headerGAUGE = 0;}
if (curmillis - prevNoconnect > 500) {NoconnectsGAUGE ++ ; if (NoconnectsGAUGE>=8){
#ifdef debugGAUGE
Serial.println (F(" Connect GAUGE failed!!! ")) ;
#endif
NoconnectsGAUGE = 0 ;InitGauge = 0 ; } prevNoconnect = curmillis; }
InitBusGAUGE (InitGauge);
}// end receiveGAUGE
void InitBusGAUGE (byte &InitGauge)
{
uint32_t prevInitbusGauge = 0; // таймер для инита щитка приборов
if (InitGauge == 0){
#ifdef debugGAUGE
Serial.println ("Send startsession - address Gauge");
#endif
K_LINE_GAUGE.end();
pinMode(TX_gauge, OUTPUT);
digitalWrite (TX_gauge, HIGH); // BUS IDLE
InitGauge = 5; prevInitbusGauge = curmillis;
}
if (InitGauge == 5 && curmillis - prevInitbusGauge>1500) {InitGauge = 6;} // BUS IDLE
if (InitGauge == 6)
{
byte boudrate = 1000/BAUD;
digitalWrite (TX_gauge, LOW); delay (boudrate); // старт бит
for (byte i=0; i<8; i++){digitalWrite (TX_gauge, bitRead(addressGUAGE, i)); delay (boudrate);} // биты тела адреса
digitalWrite (TX_gauge, HIGH); delay (boudrate); // стоп бит
K_LINE_GAUGE.begin(9600);
InitGauge = 1;
}
}
#if defined debugPCM or defined debugGAUGE
void printDebugRX (const byte &inbyte) {if (inbyte<=15) Serial.print(F("0")); Serial.print (inbyte, HEX); Serial.print (F(" "));}
#endif
#ifdef debugPCM
void printDebugRX_CSgood(const byte &n){
if (MessageRx_PCM[n]==0xC1 && MessageRx_PCM[n+1]==0x6B && MessageRx_PCM[n+2]==0x8F) {Serial.println (F(" Initialization OK!!!!")); }
else if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]==0x00) {Serial.println (F(" NO DTC "));}
else if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1] >0x00) {Serial.println (F(" DTC is found!"));}
else if (MessageRx_PCM[n]==0x54 && MessageRx_PCM[n+1]==0xFF && MessageRx_PCM[n+2]==0x00){Serial.println (F(" DTC CLEARED "));}
else if (MessageRx_PCM[n]==0x61 && MessageRx_PCM[n+1]==0x01) {Serial.println (F(" Receive PCM DATAstream"));}}
#endif
void Menu () {
TouchHOME();
if (currentPage == '0') {
TouchINF1();
TouchINF2();
TouchCHECK(); }
if (currentPage == '1') {
TouchINF2();
TouchCHECK(); }
if (currentPage == '2') {
TouchINF1();
TouchCHECK(); }
if (currentPage == '3') {
TouchREAD();
TouchERASE(); }}
void drawHomeScreen() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(80,178,80,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/L/A", 10, 180);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("OIL C", 300, 75);
myGLCD.print("FUEL C", 300, 110);
myGLCD.print("FUERA C", 300, 145);
myGLCD.print("DENTRO C", 300, 180);
myGLCD.print("INTAIR C", 300, 215);
//myGLCD.setTextColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("INF 1", 55, 270);
myGLCD.drawRoundRect (175, 255, 305, 310);
myGLCD.print("INF 2", 215, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
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.setTextColor(RED);
myGLCD.drawRoundRect (175, 255, 305, 310);
myGLCD.print("INF 2", 215, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//-------------------------------------------------
void drawscreen_two() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
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.setColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("INF 1", 55, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//----------------------------------------------------------------------------
void drawscreen_three() {
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
//myGLCD.setTextColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("ERASE", 55, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("READ", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 5);
reNew = 1;
Watch ();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//кнопки тач . координаты и переходы
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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.drawRoundRect (1, 1, 77, 37);
currentPage = '0';
request = PID; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawHomeScreen();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (15, 255, 145, 310);
currentPage = '1';
request = PID; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawscreen_one();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (175, 255, 305, 310);
currentPage = '2';
request = PID; RequestPeriod = 600; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawscreen_two();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (335, 255, 465, 310);
currentPage = '3';
// request = DTCREAD; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос чтения ошибок
myGLCD.clrScr();
drawscreen_three();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (335, 255, 465, 310);
request = DTCREAD; RequestPeriod = 300; prevRequest = curmillis; // на PCM при нажатии этой кнопки посылается запрос чтения ошибок
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (15, 255, 145, 310);
request = DTCERASE; RequestPeriod = 300; prevRequest = curmillis; // на PCM при нажатии этой кнопки посылается запрос удаления ошибок
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 180, 145);
x = 0;
y = 0;
p.z = 0;}}}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
//myGLCD.setTextColor(RED); // цвет линии красный
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 minut = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
int Year = now.year();
static int minut_last;
static int hour_last;
static int mon_last;
static int date_last;
static int Year_last;
myGLCD.setTextColor(WHITE, BLACK); //белый цвет цифры
if (date != date_last || reNew){ myGLCD.printNumI(date, 85, 7, 2, '0'); date_last = date; }
if (mon!=mon_last || reNew){myGLCD.printNumI(mon, 130, 7, 2, '0'); mon_last = mon; }
if (Year!=Year_last || reNew) { myGLCD.printNumI(Year, 175, 7); Year_last = Year; }
if (hour!=hour_last || reNew){ myGLCD.printNumI(hour, 255, 7, 2, '0'); hour_last = hour; }
if (minut!=minut_last || reNew ){ myGLCD.printNumI(minut, 300, 7, 2, '0'); minut_last = minut; }
}
void Temperature () {
static boolean p=0; // флаг работы: запрос температуры или её чтение
p=!p;
if (p) {ds.reset(); // сброс шины
ds.write(0xCC); // обращение ко всем датчикам
ds.write(0x44); // начать преобразование (без паразитного питания)
}
else {
int Temper_= 20; byte buff[9];
ds.reset();
ds.select(DSaddress);
ds.write(0xBE); // Read Scratchpad (чтение регистров)
for (byte j = 0; j<9; j++) buff[j]= ds.read(); //читаем все 9 байт от датчика
ds.reset();
if (OneWire::crc8(buff, 8) == buff[8]){ // если контрольная сумма совпадает
Temper_ = buff[0] | (buff[1]<<8); // читаем температуру из первых двух байт (остальные были нужны для проверки CRC)
Temper_ = Temper_ / 16;
if (Temper_ < 150 && Temper_ > -50 && Temper_ !=85 && Temper_!=-127) IntTemp = Temper_;
}
}
}
код похож, конечно, на говнокод с ужасным количеством глобальных переменных, потому что я писал его очень давно и не шарил толком, поэтому такие косяки сейчас и возникают.
понял, блин у меня была такая мысль что может last-ы чета мутят . но боялся уже чета трогать, чтобы не напортачить. уже на следующей недели в понедельник проверю на работе. отпишусь, спасибо
Он ищет как задать стоимость топлива в рублях для расчетов, вместо долларов. Типа сколько рублей потрачено за поездку или на данный момент сколко стоит его пройденый путь, типа того
viki13viki да так и есть.Не могу в коде найти где стоимость устанавливается с одного доллара.Стоит в меню -$1.234+.Хочу сразу переделать ,чтобы с -P40.00+ устанавливалось.По одной сотой прибавлять очень долго.Стоимость записывается в память.В принципе не нужная функция ,только ради интереса.Спасибо ,что отвечаете.
В меню я могу поставить -$40.000+ .Выставить кнопкой, долго нажимая, с одного доллара. Я не могу в коде найти почему по умолчанию стоит стоимость за 1литр от одного доллара (1.000 с тысячными), где это изменить, и чтобы ещё тысячные убрать до сотых. Бак по умолчанию в настройках стоит 45 литров, и все остальные настройки уже прописаны, где они в коде подскажите пожалуйста.
Так в том то и дело,что я не могу понять где в коде этот доллар стоит. И все остальные начальные настройки. Пример-(Бак в литрах уже стоит по умолчанию 45литров.)
последняя моя догадка, дальше я бессилен. Мне все таки кажется что задается именно здесь
/**************************/
/* GASOLINE ENGINE CONFIG */
/**************************/
// [CONFIRMED] For gas car use 3355 (1/14.7/730*3600)*10000
#define GasConst 3355
#define GasMafConst 107310 // 14.7*730*10
тебе нужно заменить 3355 на 42250 что значит у низ 3.355 и у тебя 42.25
когда заменил на 43350 изменилась цена с 1.234 доллара на другое чтото?
и в этой строке cents = fuel * params.gas_price / 1000; //now have $$$$cc
попробуй 1000 заменить на 100, станет ли цена 12.34
я одного не могу найти где прописан params.gas_price
и еще смотри здесь вроде конвертация в галоны но может от нее и пляшет
в галонах цена 3.785 и прога конвертирует в бензин и выходит 1.234 доллара
// Convert unit price to litres for the cost per gallon. (ie $1 a litre = $3.785 per gallon)
4015
fuelUnits = (fuelUnits * 378L) / 100L; //convertToLitres(params.gas_price);
4016
lcd_print_P(PSTR("G)"));
4017
}
4018
#else
4019
#ifdef UseSI
4020
lcd_print_P(PSTR("L)"));
4021
#endif
4022
#ifdef UseUS
4023
// Convert unit price to litres for the cost per gallon. (ie $1 a litre = $3.785 per gallon)
4024
fuelUnits = (fuelUnits * 378L) / 100L; //convertToLitres(params.gas_price);
4025
lcd_print_P(PSTR("G)"));
4026
#endif
4027
#endif
378L это у них 3.785 доллара из которого выходит 1.234 доллара, примерно половина. поиграй с этим значением. поставь например 2110L что есть половина 4225 . там в двух местьах нудно поменять в коде выше.
если нет, то значит, что в другом месте нужно менять. если да то эксперементируй. дальше я пас, я безпонятия.
О Командир :). Я пытаюсь помочь но из мен програмист еще тот, могу только догадывтася. в 961 строке это 1090, чет не поляшет. думпешь что это типа стоимость литра 1.9 долларов, знвяит ему нужно подставить 40025 это 40.25 в рублях?
Спасибо всем.Komandir с шагом настройки разобрался,теперь на много проще.Постоянные я так понял сразу записываются в память.После заливки кода как изменишь,остаются в памяти, после можно только подстраивать.Точно снёс память смог изменять строки 951 по 1004. Теперь вопрос где изменить в коде чтобы было 42,00 рубля а не 42,000. Строка 961 это стоимость топлива значит у меня было 1,090 доллара.Это я viki13viki в заблуждение ввёл извините.
Макс выехал домой , километров в баке 0 и средний расход 0.0. Надеялся что пробег даст первые записи и все будет норм. проехал, через 10 км показало километры в баке, средний расход 0.0. Утром включаю зажигание, литры в баке 0 и средний расход 0.0. Поехал на работу. Прогнал 30 км, как всегда после 10 км показало километры в баке, средний расход так и остался 0. Заглушил, включил, километров в баке 0 и средний расход 0.0. Вот такая вот картина.
Макс по порядку. 604-610 это у нас расчет L100SR_TFT он у нас на экране и он всегда в ноль. 614-631 это у нас L100SR (может не работает), остатки километров через 10 км начинает показывать (работает если в конце формулы 6.7 а не L100SR_TFT, не помню или с L100SR_TFT работало или нет, сегондня проверю), а вот в строчках 625-628 от туда и "продолжаем последнее значение данных" (не работает, всегда с нуля начинает). Значит заходит и считает , видно по формуле киллометров в баке если стоит 6.7, но чтото не чиатет. Остается проверить L100SR ну и на всякий случай выведу там же и L100SR_TFT, ща выведу их между 604-631, узнаем или заходит сюда прога и работает ли они. Еще одно увидел что L100SR_TFT его расчеты прописаны два раза в setup 174-179 и в voidtrip 606-610 (не знаю, может так нужно.....). Завтра скажу че да как.
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;
myGLCD.printNumF(L100SR, 1, 10, 215,'.',4);
//расчет остатка километров в баке
if (L100SR>0) kmREFUELING=((float)Fuel*100.0)/(float)L100SR; //если средний расход больше нуля, то расчитывать км в баке из него
else kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT; //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);
if ((L100SR_TFT != L100SR_TFT_last) || reNew) {myGLCD.printNumF(L100SR_TFT, 1, 225, 75,'.',4 ); L100SR_TFT_last=L100SR_TFT;}
между 604-631 на экране не отображеются эти данные, думаешь значит что не заходит сюда? тогда почму если в формуле километров в баке, которая находится межу этимх строк ставить 6.7 вместо L100SR_TFT расчет ведется? значит заходит, хз.
залей такой скетч для чисти еепром, покажи что он в сериал выведет.
#include <EEPROM.h>
void setup() {
Serial.begin(115200);
for (int i =0; i<12; i++) EEPROM.write(i, 255);
EEPROM.write(12,0);
for (int i =0; i<13; i++){ Serial.print (EEPROM.read(i)); Serial.print(" ");}
}
void loop() {
}
Потом я исправил 2053. заливай его после чистки еепром. По идее средний расход сразу должен показать 25.5. Потом начать уменьшаться раз в 15 км. и L100SR где нибудь выведи. От него средний ведь считается в ячейки еепром. Нужно посмотреть как он меняется раз в 10 км. Может ты координаты корявые при выводе сделал. Сделай маленький скетч. Проверь как эти строки на экран выводят, работает ли вывод этих строк
а вообще слишком маленькие интервалы (10км) для измерения . Ведь при расходе менее 10л/100км, за этот отрезок менее 1 литра израсходуется, а значит если десятые литра откинуть, то израсходаванных литров будет 0. Соответственно и средний расход поэтому 0. нужно делать бОльшие интервалы, хотя бы раз в 30 км.
ещё раз поправил 2053, так как при расчёте L100SR использовалась промежуточная переменная fuel_last, а она была типа int , т.е. без учёта десятых литра. а при маленьких отрезках измерения (10км) тут десятые очень важны. Исправил это
можно ещё попробовать новый подход. Заливаем этот скетч для чистки еепром. Там ставим текущие данные с панели.
//------------все для связи по K-line (тут настраиваем UARTы к-лайников, адреса блоков, скорость инита и отладку)
#include <SoftwareSerial.h>
#define TX_PCM 13
SoftwareSerial K_LINE_PCM (12, TX_PCM); //RХ,TХ //UART на котором висит K_line к PCM
#define K_LINE_GAUGE Serial2 //UART на котором висит K_line к приборке
#define TX_gauge 16 //TX UARTa на котором висит K_line к приборке
#define PCM_address 0x11 // адрес PCM
#define DIAG_address 0xF1 // адрес диагностики
const byte BAUD=200; // init baudrate - скорость инита при подключении к приборке
const byte addressGUAGE = 0xB8;// init GAUGE address - адрес щитка приборов при ините (установке связи)
#define debugPCM // раскоментировать эту строку для отладки в Serial порту обмена с PCM
//#define debugGAUGE // раскоментировать эту строку для отладки в Serial порту обмена co щитком приборов
//#define debugTRIP // раскоментировать эту строку для отладки в Serial порту данных бортовика
uint32_t curmillis = 0; // снимок текущего времени
//------------------------------------------переменные для организации протокола связи с PCM
uint32_t prevRequest = 0; // таймер периодических запосов на PCM
uint16_t RequestPeriod = 3500; // периодичность запросов на PCM
byte header = 0; // состояние заголовка
bool NOanswer_timer = 0; // таймер контроля неответов от ЭБУ после подачи запросов
uint32_t prev_NOanswer=0; // таймер контроля неответов от ЭБУ после подачи запросов
// возможные варианты запросов на ЭБУ:
enum REQUEST {INIT, PID, DTCERASE, DTCREAD, PRESENT,};
#ifdef debugPCM
// текстовки запросов для отладки
char* textRequest[] = {"INIT", "PID_2101", "DTC_ERASE", "DTC_READ", "PRESENT",} ;
#endif
// сами запросы
byte PCM_Message_TX[][5] = {
{1, 0x81, 0,0,0}, // запрос инициализации
{2, 0x21,0x01, 0,0}, // запрос пид 2101
{3, 0x14,0xFF,0x00, 0}, // запрос на стирание ошибок
{4, 0x18,0x00,0xFF,0x00 }, // запрос на чтение ошибок
{1, 0x3E, 0,0,0}, // запрос присутствия
};
byte request = INIT; // переменная, показывающая какой запрос будем делать
static byte headerGAUGE = 0; // состояние заголовка сообщений щитка приборов
const byte bufsize = 150; // размер буфера принятого сообщения
byte MessageRx_PCM [bufsize] = {0}; // буфер принятого сообщения
//-------------------------------------------переменные бортовика
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 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
int IntTemp = 0; //Температура улицы
//все что касается топлива
float Fuel = 0; //остаток топлива
float Fuel2 = 0; float Fuel2_last = 1; //остаток мгновенного топлива байт 16 , датчика в баке
float FuelIGN = 0; // количество топлива в баке на момент включения зажигания
float fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
float FuelTrip = 0; float FuelTrip_last = 1; // количество литров топлива, израсходованное за один цикл включения зажигания
//все что касается километража
float kmAge = 0; //пробег, полученный со щитка приборов
float kmAgeIGN = 0; //пробег который был в момент включения зажигания
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
float kmTrip = 0; float kmTrip_last = 1; //пробег за один цикл включения зажигания
const int kmL = 50; // интервал, через который будет происходить обновление среднего расхода на 100км
// int km = 0; // переменная для расчетов
// const int kmeeprom = 15; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
// int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING = 0; int kmREFUELING_last = 1; // пробег до заправки на остатке топлива
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
//----------------------------------------------для экрана
#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>
//#include "Fonts/Chosence_Bold16pt7b.h";
#define MINPRESSURE 200
#define MAXPRESSURE 1000
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
UTFTGLUE myGLCD(0x1581,A2,A1,A3,A4,A0); //all dummy args
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; int h_last = 1;
float t; int t_last = 1;
bool Dvoet = 0;
bool reNew = 0;
#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0xF800
#define GREEN 0x07E0
//--------------------------------------датчики t
byte DSaddress[] = {0x28, 0xFF, 0xA6, 0x19, 0xA8, 0x15, 0x01, 0xD2};
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 26
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#include <OneWire.h>
#define ONE_WIRE_BUS 22
OneWire ds(ONE_WIRE_BUS);
void setup() {
uint16_t ID = myGLCD.readID();
if (ID == 0xD3D3) ID = 0x1581; // write-only shield
myGLCD.begin(ID);
myGLCD.InitLCD(3);
myGLCD.clrScr();
myGLCD.setTextSize(2);
//myGLCD.setFont(&Chosence_Bold16pt7b);
Wire.begin();
rtc.begin();
dht.begin();
//загрузка стартовой страницы
currentPage = '0';
drawHomeScreen();
//подсчет среднеарифметического усредненного расхода
float summar = 0;
for (int i = 0; i < 20; i+=4) {float summar_; EEPROM.get (i, summar_); summar +=summar_;}
L100SR_TFT = summar/5.00;
L100SR = L100SR_TFT;
/*
int summ=0;
for (int i = 0; i < 11; i++) summ += EEPROM.read(i);
L100SR_TFT = summ / 110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
*/
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить времая и дату, залить в ардуино. в скетче закоментировать
// обратно и залить еще раз, иначе каждый раз будет по новой выствлятся это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2019, 7, 2, 10, 48, 0));
#if defined debugPCM or defined debugGAUGE or defined debugTRIP
Serial.begin(115200);
#endif
K_LINE_PCM.begin(10400);
pinMode(TX_PCM, OUTPUT);
}
void loop()
{
curmillis = millis(); // снимок текущего времени
if (curmillis - prevRequest > RequestPeriod && header == 0 )
{
if (request == INIT) fastinit(); // при необходимости делаем переподключение к PCM
else {sendMessagePCM(request); // отправляем на PCM текущий запрос
if (request == PID) RequestPeriod = 600;
if (request == DTCERASE || request == DTCREAD) RequestPeriod = 2500;}
prevRequest = curmillis;
}
receivePCM (); // приём сообщений от PCM
receiveGAUGE (); // приём сообщений от щитка приборов
if (header == 0 && headerGAUGE == 0) {Menu ();}
if (curmillis - prevWatch > 4000) { Watch (); prevWatch = curmillis; h = dht.readHumidity(); t = dht.readTemperature();Temperature ();}
//if (curmillis - prevDvoet > 500) { if (!Dvoet) {myGLCD.setTextColor(WHITE); } else {myGLCD.setTextColor(BLACK); } myGLCD.print(":", 290, 5); prevDvoet = curmillis; Dvoet=!Dvoet;}
if (curmillis - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 280, 5);} else {myGLCD.print(" ", 290, 5);} prevDvoet = curmillis; Dvoet=!Dvoet;}
Trip ();
}// end loop
void fastinit() {
digitalWrite (TX_PCM, HIGH); // bus idle
delay(1500);
digitalWrite (TX_PCM, LOW); // first part fastinit (25 ms LOW)
delay(25);
digitalWrite (TX_PCM, HIGH); // second part fastinit (25 ms HIGH)
delay(25);
K_LINE_PCM.begin(10400);
sendMessagePCM(INIT); // send start communication message
}
void receivePCM () {
static uint32_t prevRESETheader=0; // таймер сброса сообщения, если данные оборвались посередине сообщения
static bool RESETheader_timer; // таймер сброса сообщения, если данные оборвались посередине сообщения
static byte noanswers = 0; // количество подряд неответов от ЭБУ
static byte message_size = 0; // размер тела сообщения
static byte j = 3; // инкремент
static byte n = 3; // количество старт байт
static byte crc =0; // байт контрольной суммы
if (K_LINE_PCM.available() ){
// первый старт байт
if (header == 0){ MessageRx_PCM[0]=K_LINE_PCM.read();
if (MessageRx_PCM[0]!=0xFF && bitRead (MessageRx_PCM[0],7)){header = 1; RESETheader_timer = 1; prevRESETheader = curmillis;
#ifdef debugPCM
Serial.print (F("Receive PCM: ")); printDebugRX(MessageRx_PCM[0]);
#endif
}
}
// второй старт байт
else if (header == 1){ MessageRx_PCM[1]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX (MessageRx_PCM[1]);
#endif
if (MessageRx_PCM[1]==DIAG_address){ header = 2;}
else {
#ifdef debugPCM
Serial.println(F(" PCM Message fail address"));
#endif
header = 0; RESETheader_timer = 0;}}
// третий старт байт
else if (header == 2){
MessageRx_PCM[2]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX (MessageRx_PCM[2]);
#endif
if (MessageRx_PCM[2]==PCM_address){ message_size = MessageRx_PCM[0]; prevRESETheader = curmillis;
if (MessageRx_PCM[0] !=0x80) {header = 4; bitWrite (message_size, 7 , 0);j=3;n=3;}
else {header = 3; j=4;n=4;}
if (message_size > bufsize) message_size = bufsize; crc = 0;}
else {header = 0;
#ifdef debugPCM
Serial.println(F("PCM Message fail address"));
#endif
RESETheader_timer = 0;}
}
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
prevRESETheader = curmillis;
MessageRx_PCM[3]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX(MessageRx_PCM[3]);
#endif
message_size = MessageRx_PCM[3];
if (message_size > bufsize) message_size = bufsize;
crc = 0; header = 4;
}
// пишем тело сообщения
else if (header == 4 && j< message_size+n+1) {
MessageRx_PCM[j] = K_LINE_PCM.read(); prevRESETheader = curmillis;
if (j<message_size+n) crc+= MessageRx_PCM[j]; // подсчёт КС
if (j==message_size+n) header = 5;
#ifdef debugPCM
printDebugRX(MessageRx_PCM[j]);
#endif
j++; }
}
// сообщение приняли, действуем
if (header == 5) {
#ifdef debugPCM
Serial.println();
#endif
NOanswer_timer = 0; noanswers = 0; // сбрасываем таймер контроля неответов
for(byte i = 0; i<n; i++) crc+=MessageRx_PCM[i]; // прибавляем к контрольной сумме старт байты
// если контрольная сумма верна:
if ( crc == MessageRx_PCM[message_size+n])
{
#ifdef debugPCM
Serial.print (F("Received message is OK! Checksum is correct!")); Serial.print (F(" ")); Serial.println (millis()); // Если КС совпала, тут чёнибудь нужное делаем
printDebugRX_CSgood(n);
#endif
if (MessageRx_PCM[n]==0xC1 && MessageRx_PCM[n+1]==0x6B && MessageRx_PCM[n+2]==0x8F) {
if (currentPage!=3) {request = PID; RequestPeriod = 70;} else request = PRESENT, RequestPeriod = 4000; prevRequest = curmillis; // receive good INIT
}
else if (MessageRx_PCM[n]==0x58) Troublecodes (n); // DTC
else if (MessageRx_PCM[n]==0x54 && MessageRx_PCM[n+1]==0xFF && MessageRx_PCM[n+2]==0x00){ request = PRESENT; RequestPeriod = 4000; prevRequest = curmillis;} // DTC are cleared
else if (MessageRx_PCM[n]==0x61 && MessageRx_PCM[n+1]==0x01) {dataVars(n) ; RequestPeriod = 70; prevRequest = curmillis; } // receive DataStream
}
// если контрольная сумма не совпала:
#ifdef debugPCM
else Serial.println("CRC fail!!!" );
#endif
message_size = 0; header=0; RESETheader_timer = 0; j=3; crc = 0;
}
// таймер сброса целостности сообщения (если данные оборвались посередине сообщения)
if (RESETheader_timer && curmillis - prevRESETheader > 200) {
#ifdef debugPCM
Serial.println(F("Message fail timeout"));
#endif
RESETheader_timer = 0; header = 0;}
// если нет ответа после запроса: +1 к счетчику неответов. Если накопилось 6 и более: делаем реинит.
if (request!=INIT && NOanswer_timer && curmillis - prev_NOanswer > RequestPeriod - RequestPeriod/10)
{
NOanswer_timer = 0; noanswers++;
if (noanswers>=6) { noanswers = 0; request = INIT; RequestPeriod = 3500;}
}
}// end receivePCM
void Troublecodes (const byte &n)
{
if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]==0x00){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 180, 145);
}
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]>0){
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx_PCM[n+8-7]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx_PCM[n+11-7+(i*3)],6) && bitRead(MessageRx_PCM[n+11-7+(i*3)],7)){ myGLCD.setTextColor(GREEN, BLACK);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx_PCM[n+11-7+(i*3)],7) && bitRead(MessageRx_PCM[n+11-7+(i*3)],6)) { myGLCD.setTextColor(RED, BLACK);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && !bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && !bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx_PCM[n+9-7+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx_PCM[n+9-7+(i*3)]<=0x0F&&MessageRx_PCM[n+9-7+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}
if (nolA)myGLCD.print(String (MessageRx_PCM[n+9-7+(i*3)],HEX), 246, (75+y));
else myGLCD.print(String (MessageRx_PCM[n+9-7+(i*3)],HEX), 230, (75+y));
if (MessageRx_PCM[n+10-7+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx_PCM[n+10-7+(i*3)]<=0x0F&&MessageRx_PCM[n+10-7+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;}
if (nolB)myGLCD.print(String (MessageRx_PCM[n+10-7+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx_PCM[n+10-7+(i*3)],HEX), 262, (75+y));}}
request = PRESENT; RequestPeriod = 4000; prevRequest = curmillis;
}
void dataVars(const byte &n)
{
static float L100M_last = 1; //расход на 100 км измеренный за поездку
static float L100_last = 1; //мгновенный расход литров на 100км
static float LHor_last = 1; //мгновенный расход топлива литров в час
static float L100SR_TFT_last = 1; // самый средний из расходов на 100км, он выводится на экран
static int MAF_last = 1; //26,27 байты Sensor de flujo de aire en masa
static float BoostPres_last = 1; //28,29 байты Presión de refuerzo
static int RPM_last = 1; //32,33 байты Velocidad del motor
static int EGRmg_last = 1; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
static float BoostPresCom_last = 1;//38,39 байты Comando de presión de refuerzo
static int Speed_last = 1; //44,45 байты Velocidad del vehículo
static float DesaInjQua_last = 1; //50,51 байты Cantidad de inyección deseada
static float InjQua_last = 1; //52,53 байты Cantidad de la inyección
static float StaDaliv_last = 1; //54,55 байты Inicio de la entrega
static int PumpRPM_last = 1; //56,57 байты Velocidad de la bomba
static float EGRPul_last = 1; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
static float SolenPul_last = 1; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
static float SolenPre_last = 1; //70,71 байты Relación de impulsos Presión Electroválvula de presión
static float DesInj_last = 1; //72,73 байты Inyección deseada Inicio
static float ActInj_last = 1; //16,17 байты Inicio de la inyección real
static int TempAir_last = 1; //74,75 байты Temperatura del aire de admisión
static int Temp_last = 1; //14,15 байты Temperatura del refrigerante
static int TempOil_last = 1; //18,19 байты Temperatura del aceite del motor
static int TempFuel_last = 1; //58,59 байты Temperatura del combustible
static int IntTemp_last = 1; //Температура улицы
static float Fuel_last = 1; //уровень топлива в баке
//Barom = MessageRx_PCM[39];
MAF = ((MessageRx_PCM[n+22]*256)+MessageRx_PCM[n+23])/10;
BoostPres = ((MessageRx_PCM[n+24]*256)+MessageRx_PCM[n+25])/1000.0;
RPM = (MessageRx_PCM[n+35-7]*256)+MessageRx_PCM[n+36-7];
EGRmg = ((MessageRx_PCM[n+37-7]*256)+MessageRx_PCM[n+38-7])/10.0;
BoostPresCom = ((MessageRx_PCM[n+41-7]*256)+MessageRx_PCM[n+42-7])/1000.0;
Speed = ((MessageRx_PCM[n+47-7]*256)+MessageRx_PCM[n+48-7])/100;
DesaInjQua = ((MessageRx_PCM[n+53-7]*256)+MessageRx_PCM[n+54-7])/100.0;
InjQua = ((MessageRx_PCM[n+55-7]*256)+MessageRx_PCM[n+56-7])/100.0;
StaDaliv = ((MessageRx_PCM[n+57-7]*256)+MessageRx_PCM[n+58-7])/100.0;
PumpRPM = (MessageRx_PCM[n+59-7]*256)+MessageRx_PCM[n+60-7];
EGRPul = ((MessageRx_PCM[n+65-7]*256)+MessageRx_PCM[n+66-7])/100.0;
SolenPul = ((MessageRx_PCM[n+67-7]*256)+MessageRx_PCM[n+68-7])/100.0;
SolenPre = ((MessageRx_PCM[n+73-7]*256)+MessageRx_PCM[n+74-7])/100.0;
DesInj = ((MessageRx_PCM[n+75-7]*3)+(MessageRx_PCM[n+76-7])/100.0)+0.3;
ActInj = ((MessageRx_PCM[n+19-7]*3)+(MessageRx_PCM[n+20-7])/100.0)+0.3;
//TempAir = ((MessageRx_PCM[n+77-7]*26)-278)+MessageRx_PCM[n+78-7]/10.0;
//Temp = ((MessageRx_PCM[n+17-7]*26)-278)+MessageRx_PCM[n+18-7]/10.0;
//TempOil = ((MessageRx_PCM[n+21-7]*26)-278)+MessageRx_PCM[n+22-7]/10.0;
//TempFuel = ((MessageRx_PCM[n+61-7]*26)-278)+MessageRx_PCM[n+62-7]/10.0;
//ниже идут расчетные формулы более точные чем те что закоментированы выше
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
if (Speed!=0) L100 = (float)LHor*100.0/(float)Speed;
else L100 = 99;
int A = 0;
if (MessageRx_PCM[n+77-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+77-7]==0x0B || MessageRx_PCM[n+77-7]==0x0C) A = 278;
if (MessageRx_PCM[n+77-7]>=0x0D) A = 279;
double B = MessageRx_PCM[n+78-7]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx_PCM[n+77-7]*26)-A)+cel;
if (MessageRx_PCM[n+17-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+17-7]==0x0B || MessageRx_PCM[n+17-7]==0x0C) A = 278;
if (MessageRx_PCM[n+17-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+18-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx_PCM[n+17-7]*26)-A)+cel;
if (MessageRx_PCM[n+21-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+21-7]==0x0B || MessageRx_PCM[n+21-7]==0x0C) A = 278;
if (MessageRx_PCM[n+21-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+22-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx_PCM[n+21-7]*26)-A)+cel;
if (MessageRx_PCM[n+61-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+61-7]==0x0B || MessageRx_PCM[n+61-7]==0x0C) A = 278;
if (MessageRx_PCM[n+61-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+62-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx_PCM[n+61-7]*26)-A)+cel;
//----------------------------------------------------------
//страниц HOME
//----------------------------------------------------------
//myGLCD.setBackColor(RED);
myGLCD.setTextColor(WHITE, BLACK);
//myGLCD.setBackColor(RED);
if ((Speed != Speed_last) || reNew) {myGLCD.printNumI(Speed, 360, 7, 3); Speed_last=Speed;}
if (currentPage == '0') {
if ((LHor != LHor_last) || reNew) {myGLCD.printNumF(LHor, 1, 75, 40, '.',4); LHor_last=LHor;}
if ((L100 != L100_last) || reNew) {myGLCD.printNumF(L100, 1, 225, 40,'.',4 ); L100_last=L100;}
if ((L100M != L100M_last) || reNew) {myGLCD.printNumF(L100M, 1, 75, 75,'.',4 ); L100M_last=L100M;}
if ((L100SR_TFT != L100SR_TFT_last) || reNew) {myGLCD.printNumF(L100SR_TFT, 1, 225, 75,'.',4 ); L100SR_TFT_last=L100SR_TFT;}
if ((kmREFUELING != kmREFUELING_last) || reNew) {myGLCD.printNumI(kmREFUELING, 90, 110,3 ); kmREFUELING_last=kmREFUELING;}
//if (Fuel<53)
if ((Fuel != Fuel_last) || reNew) {myGLCD.printNumF(Fuel, 1, 225, 110,'.',4); Fuel_last=Fuel;}
//else myGLCD.print("MAX", 210, 110);
if ((kmTrip != kmTrip_last) || reNew) {myGLCD.printNumF(kmTrip, 1, 60, 145,'.',5); kmTrip_last=kmTrip;}
if ((FuelTrip != FuelTrip_last) || reNew) {myGLCD.printNumF(FuelTrip, 1, 210, 145,'.',5); FuelTrip_last=FuelTrip;}
if ((PumpRPM != PumpRPM_last) || reNew) {myGLCD.printNumI(PumpRPM, 230, 180,4); PumpRPM_last=PumpRPM;}
if ((RPM != RPM_last) || reNew) {myGLCD.printNumI(RPM, 230, 215,4); RPM_last=RPM;}
if ((Fuel2 != Fuel2_last) || reNew) {myGLCD.printNumF(Fuel2, 1, 10, 215,'.',4); Fuel2_last=Fuel2;}
if ((Temp != Temp_last) || reNew) {myGLCD.printNumI(Temp, 415, 40, 3); Temp_last=Temp;}
if ((TempOil != TempOil_last) || reNew) {myGLCD.printNumI(TempOil, 415, 75, 3); TempOil_last=TempOil;}
if ((TempFuel != TempFuel_last) || reNew) {myGLCD.printNumI(TempFuel, 415, 110,3); TempFuel_last=TempFuel;}
if ((IntTemp != IntTemp_last) || reNew) {myGLCD.printNumI(IntTemp, 415, 145 , 3); IntTemp_last=IntTemp;}
if ((t != t_last) || reNew) {myGLCD.printNumI(t, 415, 180, 3); t_last=t;}
if ((TempAir != TempAir_last) || reNew) {myGLCD.printNumI(TempAir, 415, 215, 3); TempAir_last=TempAir;}
reNew = 0;
}
//----------------------------------------------------------
//страниц INF1
//----------------------------------------------------------
if (currentPage == '1') {
if ((StaDaliv != StaDaliv_last) || reNew) {myGLCD.printNumF(StaDaliv,1, 385, 40,'.', 4); StaDaliv_last=StaDaliv;}
if ((DesInj != DesInj_last) || reNew) {myGLCD.printNumF(DesInj,1, 385, 75, '.', 4); DesInj_last=DesInj;}
if ((ActInj != ActInj_last) || reNew) {myGLCD.printNumF(ActInj,1, 385, 110,'.', 4); ActInj_last=ActInj;}
if ((DesaInjQua != DesaInjQua_last) || reNew) {myGLCD.printNumF(DesaInjQua,1, 385, 145,'.', 4);DesaInjQua_last=DesaInjQua;}
if ((InjQua != InjQua_last) || reNew) {myGLCD.printNumF(InjQua,1, 385, 180,'.', 4); InjQua_last=InjQua;}
if ((MAF != MAF_last) || reNew) {myGLCD.printNumI(MAF, 170, 215, 4); MAF_last=MAF;}
if ((h != h_last) || reNew) {myGLCD.printNumF(h, 1, 430, 215, 3); h_last=h;}
reNew = 0;
}
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
if ((BoostPres != BoostPres_last) || reNew) {myGLCD.printNumF(BoostPres,1, 400, 40,'.', 4); BoostPres_last=BoostPres;}
if ((BoostPresCom != BoostPresCom_last) || reNew) {myGLCD.printNumF(BoostPresCom,1, 400, 75,'.', 4); BoostPresCom_last=BoostPresCom;}
if ((EGRmg != EGRmg_last) || reNew) {myGLCD.printNumI(EGRmg, 400, 110, 4); EGRmg_last=EGRmg;}
if ((EGRPul != EGRPul_last) || reNew) {myGLCD.printNumF(EGRPul,1, 400, 145,'.', 4); EGRPul_last=EGRPul;}
if ((SolenPul != SolenPul_last) || reNew) {myGLCD.printNumF(SolenPul, 1, 400, 180,'.', 4); SolenPul_last=SolenPul;}
if ((SolenPre != SolenPre_last) || reNew) {myGLCD.printNumF(SolenPre, 0, 400, 215,'.', 4); SolenPre_last=SolenPre;}
reNew = 0;
}
//reNew = 0;
}
void sendMessagePCM(const byte &command)
{
#ifdef debugPCM
Serial.print (F("Send request ")); Serial.print (textRequest[command]); Serial.print (F(" to PCM ")); Serial.println (millis());
#endif
if (command != INIT) {NOanswer_timer = 1; prev_NOanswer = curmillis;} //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов
byte size = PCM_Message_TX[command][0];
const byte siZe = size+4;
byte Mes[siZe];
byte Checksum = 0;
for(byte i=0; i<siZe; i++) {
if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
if (i==1) Mes[i] = PCM_address;
if (i==2) Mes[i] = DIAG_address;
if (i==3) {for (byte t=1; t<size+1; t++ ) {
Mes[i]=PCM_Message_TX [command][t];
Checksum+=Mes[i] ;
K_LINE_PCM.write (Mes[i]);
if (command == INIT) delay (5); else delay (1);
K_LINE_PCM.read();
i++;}}
if (i!=siZe-1) Checksum+=Mes[i];
else Mes[i] = Checksum;
K_LINE_PCM.write (Mes[i]);
if (command == INIT) delay (5); else delay (1);
K_LINE_PCM.read();
}
}// end sendMessagePCM
void Trip ()
{
static uint32_t prevRefueling = 0;
if (curmillis - prevRefueling>1000)
{ static float rashod [60]={0};
static byte yacheyka_numer = 0;
rashod[yacheyka_numer] = L100;
if (yacheyka_numer == 59)
{
//-----------------расчет среднего расхода
float km_prev = 0;
EEPROM.get (130, km_prev); // считываем из еепром пробег прошлого измерения каждую минуту
float kmTrip_refuel = 0;
if (kmAge>km_prev) kmTrip_refuel = kmAge - km_prev;
if (kmAge<km_prev) kmTrip_refuel = 2000 - (km_prev - kmAge);
if (kmAge==km_prev) kmTrip_refuel = 0;
if (kmTrip_refuel >=kmL) {
float l_prev = 0;
EEPROM.get (140, l_prev); // считываем из еепром уровень топлива прошлого измерения
if (l_prev-Fuel > 0) L100SR = ((float)(l_prev-Fuel)*100.00)/(float)kmL;
EEPROM.put (140, Fuel); // записываем в еепром уровень топлива текущего измерения
EEPROM.put (130, kmAge); // записываем в еепром пробег текущего измерения
byte n_eeprom = EEPROM.read (150); // в ячейке 150 хранится № текущей ячейки для записи расхода, чтобы где остановился при выкл питания, от туда и продолжил
EEPROM.put(n_eeprom, L100SR);
n_eeprom+=4; if (n_eeprom>16) n_eeprom=0;
EEPROM.write (150,n_eeprom);
float summar = 0.0;
for (int i = 0; i < 20; i+=4) {float summar_=0.0; EEPROM.get (i, summar_); summar +=summar_;}
L100SR_TFT = summar/5.00;
}
//-----------------расчет пробега до заправки
static byte yacheyka_number=0;
static float rashod_sr[20]={0};
float summa = 0.00;
for (int i = 0; i<60; i++) {summa+=rashod [i];}
summa/=60.00;
rashod_sr[yacheyka_number] = summa;
if (yacheyka_number == 19) {
float summasr = 0.00;
for (int i = 0; i<20; i++) {summasr+=rashod_sr [i];}
summasr/=20.00;
kmREFUELING=Fuel*100.00/summasr;}// end of 20 minuts;
yacheyka_number++; if (yacheyka_number>19) yacheyka_number = 0;
} // end of 1 minuts
//---------------расчёт пробега и расхода за поездку
if (yacheyka_numer == 5) {
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;
}}
yacheyka_numer++; if (yacheyka_numer>59) yacheyka_numer = 0;
prevRefueling = curmillis;
}
}
/*
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;
// тут считаем среднеарифметический усредненного расхода из ячеек еепром
int summ = 0;
for (int i = 0; i < 11; i++) summ += EEPROM.read(i);
L100SR_TFT = summ / 110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 25;}
// ниже цикл считает расход топлива за пробег, указанный в переменной 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); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
byte 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);
#ifdef debugTRIP
Serial.println (" I am heer: if (kmTrip-km>kmL) {} ");
Serial.print (" L100SR = "); Serial.print (L100SR) ; Serial.println (" L/100km");
Serial.print (" kmREFUELING = "); Serial.print (kmREFUELING) ; Serial.println (" km");
#endif
}
#ifdef debugTRIP
Serial.print (" FuelTrip = "); Serial.print (FuelTrip); Serial.println (" L");
Serial.print (" kmTrip = "); Serial.print (kmTrip); Serial.println (" km");
Serial.print (" L100SR_TFT = "); Serial.print (L100SR_TFT); Serial.println (" L/100km");
#endif
}}
*/
void receiveGAUGE () {
static uint32_t prevRESETheaderGAUGE=0; // таймер сброса сообщения, если данные оборвались посередине сообщения
static bool RESETheader_timerGAUGE; // таймер сброса сообщения, если данные оборвались посередине сообщения
static uint32_t prevNoconnect = 0; // таймер периодической проверки наличия связи со щитком приборов
static byte NoconnectsGAUGE = 0 ; // счетчик неответов от щитка приборов
static byte message_sizeGAUGE = 0; // размер тела сообщения
static byte jGAUGE = 3; // инкремент
static byte nGAUGE = 3; // количество старт байт
static int ChecksumGAUGE =0; // байт контрольной суммы
static byte InitGauge = 0; // автомат состояния инита щитка приборов
const byte bufsizeG = 100; // размер буфера принятого сообщения
static byte MessageRx_GAUGE [bufsizeG] = {0}; // буфер принятого сообщения
byte PIDgauge[] = {0x02,0x11,0x00,0x13}; // запрос параметоров щитка приборов
if (K_LINE_GAUGE.available() ){
// первый старт байт
if (headerGAUGE == 0){ MessageRx_GAUGE[0]=K_LINE_GAUGE.read();
if ((InitGauge ==1 && MessageRx_GAUGE[0]==0x55) || (InitGauge ==2 && MessageRx_GAUGE[0]!=0xFF && MessageRx_GAUGE[0]!=0x7F)
|| (InitGauge ==3 && MessageRx_GAUGE[0]==0x23)
)
{headerGAUGE = 1; RESETheader_timerGAUGE = 1; prevRESETheaderGAUGE = curmillis;
#ifdef debugGAUGE
Serial.print (F("Receive GAUGE: ")); printDebugRX(MessageRx_GAUGE[0]);
#endif
}
}
// второй старт байт
else if (headerGAUGE == 1){ MessageRx_GAUGE[1]=K_LINE_GAUGE.read();
#ifdef debugGAUGE
printDebugRX (MessageRx_GAUGE[1]);
#endif
if ( (InitGauge ==1 && MessageRx_GAUGE[1]==0x52) || (InitGauge ==2 && (MessageRx_GAUGE[1]==0xA0 || MessageRx_GAUGE[1]==0xF0))
|| (InitGauge == 3 && MessageRx_GAUGE[1]==0xA1)){ headerGAUGE = 2;}
else {
#ifdef debugGAUGE
Serial.println(F(" GAUGE Message fail address"));
#endif
headerGAUGE = 0; RESETheader_timerGAUGE = 0;}}
// третий старт байт
else if (headerGAUGE == 2){
MessageRx_GAUGE[2]=K_LINE_GAUGE.read();
#ifdef debugGAUGE
printDebugRX (MessageRx_GAUGE[2]);
#endif
if ((InitGauge ==2 && (MessageRx_GAUGE[2]==0x48 || MessageRx_GAUGE[2]==0x55 || MessageRx_GAUGE[2]==0xAA)) || (InitGauge == 3 && MessageRx_GAUGE[2]==0x04)){ message_sizeGAUGE = MessageRx_GAUGE[0]-2; prevRESETheaderGAUGE = curmillis;
headerGAUGE = 4; jGAUGE=3; nGAUGE=3;
if (message_sizeGAUGE > bufsizeG) message_sizeGAUGE = bufsizeG; ChecksumGAUGE = 0;}
else if (InitGauge ==1 && MessageRx_GAUGE[2]==0x80) {InitGauge = 2; K_LINE_GAUGE.write(0x7F); delay (2); K_LINE_GAUGE.read(); headerGAUGE = 0; RESETheader_timerGAUGE = 0;
#ifdef debugGAUGE
Serial.println ("Gauge INIT is good!");
#endif
}
else {headerGAUGE = 0;
#ifdef debugGAUGE
Serial.println(F("GAUGE Message fail address"));
#endif
RESETheader_timerGAUGE = 0;}
}
// пишем тело сообщения
else if (headerGAUGE == 4 && jGAUGE< message_sizeGAUGE+nGAUGE+1) {
MessageRx_GAUGE[jGAUGE] = K_LINE_GAUGE.read(); prevRESETheaderGAUGE = curmillis;
if (jGAUGE<message_sizeGAUGE+nGAUGE-1) ChecksumGAUGE+= MessageRx_GAUGE[jGAUGE]; // подсчёт КС
if (jGAUGE==message_sizeGAUGE+nGAUGE) headerGAUGE = 5;
#ifdef debugGAUGE
printDebugRX(MessageRx_GAUGE[jGAUGE]);
#endif
jGAUGE++; }
}
// сообщение приняли, действуем
if (headerGAUGE == 5) {
#ifdef debugGAUGE
Serial.println();
#endif
for(byte i = 0; i<nGAUGE; i++) ChecksumGAUGE+=MessageRx_GAUGE[i]; // прибавляем к контрольной сумме старт байты
int ChecksumG = ( ( unsigned int )MessageRx_GAUGE[message_sizeGAUGE+nGAUGE-1] << 8 ) | MessageRx_GAUGE[message_sizeGAUGE+nGAUGE]; // парсинг контрольной суммы из 2 последних байт
// если контрольная сумма верна:
if ( ChecksumGAUGE == ChecksumG)
{ NoconnectsGAUGE = 0; // сбрасываем на 0 отсутствие связи с панелью
#ifdef debugGAUGE
Serial.print (F("Received message is OK! Checksum is correct!")); Serial.print (F(" ")); Serial.println (millis()); // Если КС совпала, тут чёнибудь нужное делаем
#endif
if (MessageRx_GAUGE[1]== 0xA0 && MessageRx_GAUGE[2]== 0x48) {
#ifdef debugGAUGE
Serial.println ("ID panel receive! Send request PIDGauge");
#endif
InitGauge = 3;
for (byte i=0; i<sizeof(PIDgauge); i++) { K_LINE_GAUGE.write (PIDgauge[i]); delay (1); K_LINE_GAUGE.read();}
}
if (MessageRx_GAUGE[1]== 0xF0 && (MessageRx_GAUGE[2]== 0xAA || MessageRx_GAUGE[2]== 0x55)) {
#ifdef debugGAUGE
Serial.println ("receive present from Gauge. I send PID to Gauge");
#endif
InitGauge = 3;
for (byte i=0; i<sizeof(PIDgauge); i++) { K_LINE_GAUGE.write (PIDgauge[i]); delay (1); K_LINE_GAUGE.read();}
}
if (MessageRx_GAUGE[1]== 0xA1 && MessageRx_GAUGE[2]== 0x04) {
#ifdef debugGAUGE
Serial.println (" receive Datastream Gauge!");
#endif
Fuel2 = MessageRx_GAUGE[nGAUGE + 16]/2.0;
if (!flagFuelIGN) { Fuel = MessageRx_GAUGE[nGAUGE + 16]/2.0; kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;} //стартовая запись литров в баке для подсчета затраченных литро
else Fuel = MessageRx_GAUGE[nGAUGE + 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 = (MessageRx_GAUGE[nGAUGE + 23]+(MessageRx_GAUGE[nGAUGE + 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;}}
#ifdef debugTRIP
Serial.print (" Fuel = "); Serial.print (Fuel); Serial.println (" L");
Serial.print (" kmAge = "); Serial.print (kmAge); Serial.println (" km");
#endif
}
}
// если контрольная сумма не совпала:
#ifdef debugGAUGE
else Serial.println("CRC fail!!!" );
#endif
message_sizeGAUGE = 0; headerGAUGE=0; RESETheader_timerGAUGE = 0; jGAUGE=3; ChecksumGAUGE = 0;
}
// таймер сброса целостности сообщения (если данные оборвались посередине сообщения)
if (RESETheader_timerGAUGE && curmillis - prevRESETheaderGAUGE > 300) {
#ifdef debugGAUGE
Serial.println(F("Message fail timeout"));
#endif
RESETheader_timerGAUGE = 0; headerGAUGE = 0;}
if (curmillis - prevNoconnect > 500) {NoconnectsGAUGE ++ ; if (NoconnectsGAUGE>=8){
#ifdef debugGAUGE
Serial.println (F(" Connect GAUGE failed!!! ")) ;
#endif
NoconnectsGAUGE = 0 ;InitGauge = 0 ; } prevNoconnect = curmillis; }
InitBusGAUGE (InitGauge);
}// end receiveGAUGE
void InitBusGAUGE (byte &InitGauge)
{
uint32_t prevInitbusGauge = 0; // таймер для инита щитка приборов
if (InitGauge == 0){
#ifdef debugGAUGE
Serial.println ("Send startsession - address Gauge");
#endif
K_LINE_GAUGE.end();
pinMode(TX_gauge, OUTPUT);
digitalWrite (TX_gauge, HIGH); // BUS IDLE
InitGauge = 5; prevInitbusGauge = curmillis;
}
if (InitGauge == 5 && curmillis - prevInitbusGauge>1500) {InitGauge = 6;} // BUS IDLE
if (InitGauge == 6)
{
byte boudrate = 1000/BAUD;
digitalWrite (TX_gauge, LOW); delay (boudrate); // старт бит
for (byte i=0; i<8; i++){digitalWrite (TX_gauge, bitRead(addressGUAGE, i)); delay (boudrate);} // биты тела адреса
digitalWrite (TX_gauge, HIGH); delay (boudrate); // стоп бит
K_LINE_GAUGE.begin(9600);
InitGauge = 1;
}
}
#if defined debugPCM or defined debugGAUGE
void printDebugRX (const byte &inbyte) {if (inbyte<=15) Serial.print(F("0")); Serial.print (inbyte, HEX); Serial.print (F(" "));}
#endif
#ifdef debugPCM
void printDebugRX_CSgood(const byte &n){
if (MessageRx_PCM[n]==0xC1 && MessageRx_PCM[n+1]==0x6B && MessageRx_PCM[n+2]==0x8F) {Serial.println (F(" Initialization OK!!!!")); }
else if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]==0x00) {Serial.println (F(" NO DTC "));}
else if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1] >0x00) {Serial.println (F(" DTC is found!"));}
else if (MessageRx_PCM[n]==0x54 && MessageRx_PCM[n+1]==0xFF && MessageRx_PCM[n+2]==0x00){Serial.println (F(" DTC CLEARED "));}
else if (MessageRx_PCM[n]==0x61 && MessageRx_PCM[n+1]==0x01) {Serial.println (F(" Receive PCM DATAstream"));}}
#endif
void Menu () {
TouchHOME();
if (currentPage == '0') {
TouchINF1();
TouchINF2();
TouchCHECK(); }
if (currentPage == '1') {
TouchINF2();
TouchCHECK(); }
if (currentPage == '2') {
TouchINF1();
TouchCHECK(); }
if (currentPage == '3') {
TouchREAD();
TouchERASE(); }}
void drawHomeScreen() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(80,178,80,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/L/A", 10, 180);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("OIL C", 300, 75);
myGLCD.print("FUEL C", 300, 110);
myGLCD.print("FUERA C", 300, 145);
myGLCD.print("DENTRO C", 300, 180);
myGLCD.print("INTAIR C", 300, 215);
//myGLCD.setTextColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("INF 1", 55, 270);
myGLCD.drawRoundRect (175, 255, 305, 310);
myGLCD.print("INF 2", 215, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
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.setTextColor(RED);
myGLCD.drawRoundRect (175, 255, 305, 310);
myGLCD.print("INF 2", 215, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//-------------------------------------------------
void drawscreen_two() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
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.setColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("INF 1", 55, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//----------------------------------------------------------------------------
void drawscreen_three() {
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
//myGLCD.setTextColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("ERASE", 55, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("READ", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 5);
reNew = 1;
Watch ();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//кнопки тач . координаты и переходы
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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.drawRoundRect (1, 1, 77, 37);
currentPage = '0';
request = PID; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawHomeScreen();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (15, 255, 145, 310);
currentPage = '1';
request = PID; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawscreen_one();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (175, 255, 305, 310);
currentPage = '2';
request = PID; RequestPeriod = 600; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawscreen_two();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (335, 255, 465, 310);
currentPage = '3';
// request = DTCREAD; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос чтения ошибок
myGLCD.clrScr();
drawscreen_three();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (335, 255, 465, 310);
request = DTCREAD; RequestPeriod = 300; prevRequest = curmillis; // на PCM при нажатии этой кнопки посылается запрос чтения ошибок
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (15, 255, 145, 310);
request = DTCERASE; RequestPeriod = 300; prevRequest = curmillis; // на PCM при нажатии этой кнопки посылается запрос удаления ошибок
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 180, 145);
x = 0;
y = 0;
p.z = 0;}}}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
//myGLCD.setTextColor(RED); // цвет линии красный
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 minut = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
int Year = now.year();
static int minut_last;
static int hour_last;
static int mon_last;
static int date_last;
static int Year_last;
myGLCD.setTextColor(WHITE, BLACK); //белый цвет цифры
if (date != date_last || reNew){ myGLCD.printNumI(date, 85, 7, 2, '0'); date_last = date; }
if (mon!=mon_last || reNew){myGLCD.printNumI(mon, 130, 7, 2, '0'); mon_last = mon; }
if (Year!=Year_last || reNew) { myGLCD.printNumI(Year, 175, 7); Year_last = Year; }
if (hour!=hour_last || reNew){ myGLCD.printNumI(hour, 255, 7, 2, '0'); hour_last = hour; }
if (minut!=minut_last || reNew ){ myGLCD.printNumI(minut, 300, 7, 2, '0'); minut_last = minut; }
}
void Temperature () {
static boolean p=0; // флаг работы: запрос температуры или её чтение
p=!p;
if (p) {ds.reset(); // сброс шины
ds.write(0xCC); // обращение ко всем датчикам
ds.write(0x44); // начать преобразование (без паразитного питания)
}
else {
int Temper_= 20; byte buff[9];
ds.reset();
ds.select(DSaddress);
ds.write(0xBE); // Read Scratchpad (чтение регистров)
for (byte j = 0; j<9; j++) buff[j]= ds.read(); //читаем все 9 байт от датчика
ds.reset();
if (OneWire::crc8(buff, 8) == buff[8]){ // если контрольная сумма совпадает
Temper_ = buff[0] | (buff[1]<<8); // читаем температуру из первых двух байт (остальные были нужны для проверки CRC)
Temper_ = Temper_ / 16;
if (Temper_ < 150 && Temper_ > -50 && Temper_ !=85 && Temper_!=-127) IntTemp = Temper_;
}
}
}
здесь применил расчёт среднего расхода с измерениями на больших дистанциях в 50км для увеличения точности. А данные сохраняются в еепром ,т.к. за одну поездку не всегда получается проезжать 50 км, поэтому при старте МК измерения продолжатся с последнего момента. Т.е. проехали 30 км, в следующий раз он и считает уже с 30 км, т.е. нужно ещё 20 проехать для того, чтобы произошло измерение.
а расчёт пробега до заправки сделан по мгновенному расходу с помощью интегрирования (среднеарифметическое между 60 измерениями, которые делаются раз в 15 сек). Т.е. этот параметр обновляется раз в 15 минут.
звучит круто. значит заливаю первый, подставив данные, и потом заливаю второй и сегодня прокатить?
сделал. поставил 1744 км, 12 литров, и 6.7 расход, залил. Потом залил второй, на экране показало средний 6.7 , и расчитало бак на 164 км, актуальный расход 99.0. завтра отпишу после пробега
я так понимаю по 2083 до исправления ошибок нет смысла отчитыватся. Но тем не мение. Вчера пройдено около 35км. Со старта расчет километров в баке был реальным 170 км, через киллометров 15 стало 23 км в баке и так аж до дома. Средний со старта так и остался 6.7 л на 100 км. Утром выехал сново со старта было км в баке реально спустя 11-15 км сново показал занижено гдето 20 с чемто. Средний оставался 6.7 л на 100 км. Проехал 20 км заехал на заправку. заправил бак на полную. Завел и сбросил суточный на ноль, и сразу показало что я 200 км уже проехал, не стал заморачиватся глушить, поехал дальше. Км в баке показало на 805 км. Доезжая до работы пройдя километров 6 , вдруг средний расход сменился на 5.4 л на 100 км, км в баке так и остались на 805 км. На работе заглушил и включил показало средний 5.4 и км в баке 1007 км. Может какието выводы можно из этого сделать. Сегодня залью подправленый 2083, если я сейчас его залью 10 км хватит для теста? учитываю что буду гонять по кругу большому с поворотами и маленькими спусками и подьемчиками учитывая что будет сильная болтанка в баке, это даст какойто результат для проверки? или лучше уже вечером домой сделать нормальный прогон?
пробег до заправки очень коряво должен был показывать, в этом и была ошибка , я там формулу не ту написал. так что тут нечему удивляться. При заправке не надо скидывать суточный на ноль. Этим самым ты вводишь в ступор бортовик. Через 2000 км на ноль он сам безболезненно должен перепрыгивать . Если заправился , по идее один из расчетов среднего расхода просто должен пропуститься , т.е. следующие 50 км после заправки средний расход будет без изменений.
аа, ну тогда надо и на бортовике делать кнопку сброса этих значений, а то не корректно будет одно измерение, от слова совсем. Логика в новом скетче такая.
Расчёт среднего расхода происходит раз в 50км при отсутствии заправки и сброса суточного пробега.
Расчёт пробега до заправки делается так: в течение одной минуты раз в секунду записывается мгновенный расход. Итого имеем 60 значений. Считаем среднее арифметическое. Далее это среднее опять записывается в массив из 20 значений. По истечении записи в этот массив (двадцатое значение) считается опять среднеарифметический расход на сотню и уже здесь и считается пробег до заправки. Таким образом пробег до заправки обновляется раз в 20 минут . Соответственно если мы стоим и не едем, то расход записывается по 99 л/100км. Поэтому в пробках расстояние до заправки будет снижаться.
Не знаю на сколько такой алгоритм будет адекватен.
Раньше я всегда так делал, но у меня было задано расход 7.6 в формуле. С другой стороны он же считает по пробегом за поездку а не от полной суточной цифры. Или ты что-то изменил?
Я думаю чтобы уже не парится, просто км в баке я подкину 6.7, меня очень устраивало, нужно только со средним расходом сделать порядок, и фиг с ним.
изменил . Теперь значения пробега и количества литров от прошлого измерения сохраняются в еепром. А раньше каждое измерение происходило в пределах одного цикла зажигания. Теперь же, включая зажигание, мы как бы продолжаем измерение, пока не наступит разница в 50 км . между текущем пробегом и сохранённом в еепром .
Я понял. Но сброс для меня как подстраховка, в принципе если бы бортовиков выдавал более менее правдиво и стабильно а не с прыжкам то 500 то 320 и т.д, я бы не сбрасывал. Хз, стоит ли так усложнятся. Меня бы устроило 6.7 в формуле и просто упорядочить вывод среднего расхода, ты уже наверняка замучился с моим скетчем.
Ок. Понял 250 км не сбрасывая. Не до понял другое, если прийдет средний в норму.. ( Типа допустим 6.9 пришёл в норму), будешь пробег до заправки от него считать. Что ты имеешь в виду?
Макс дела такие.... спустя 400 км пробега наконец то вышло на примерно правдивое показание 7.6 л на 100 , в начале теста было 5.4 потом в течении времени падало и упало до 3.4 и потом начало потихоньку расти и сегодня вышло на 7.6 а вечером на 8.4, но.... все это время происходило такое, километры в баке со старта показывают правильно спустя пару минут падает очень низко, например, сегодня включил зажигание км в баке 415 что есть верно, спустя пару минут упало до 51 км в баке, спустя 10 или 15 км прогона стало 10 км в баке и спустя 27 км пробега показало 26 км в баке. Похоже косяк происходит из за того что я тогда сбил суточный. Как убрать эту зависимость от полного цикла суточного пробега. Я так понимаю что от привязки к целому суточному циклу средний расход от этого зависит а за ним уже и км в баке пляшут. Так как привычка сбивать при следующей полной заправке не уйдет, и будут вечно косяки может вернуть как то логику как была раньше, я все время сбивал суточный и на средний расход это никак не влияло а км в баке было в формуле подставлен мой средний расход 6.7. Вот скетч с последними под правками которые ты говорил
//------------все для связи по K-line (тут настраиваем UARTы к-лайников, адреса блоков, скорость инита и отладку)
#include <SoftwareSerial.h>
#define TX_PCM 13
SoftwareSerial K_LINE_PCM (12, TX_PCM); //RХ,TХ //UART на котором висит K_line к PCM
#define K_LINE_GAUGE Serial2 //UART на котором висит K_line к приборке
#define TX_gauge 16 //TX UARTa на котором висит K_line к приборке
#define PCM_address 0x11 // адрес PCM
#define DIAG_address 0xF1 // адрес диагностики
const byte BAUD=200; // init baudrate - скорость инита при подключении к приборке
const byte addressGUAGE = 0xB8;// init GAUGE address - адрес щитка приборов при ините (установке связи)
#define debugPCM // раскоментировать эту строку для отладки в Serial порту обмена с PCM
//#define debugGAUGE // раскоментировать эту строку для отладки в Serial порту обмена co щитком приборов
//#define debugTRIP // раскоментировать эту строку для отладки в Serial порту данных бортовика
uint32_t curmillis = 0; // снимок текущего времени
//------------------------------------------переменные для организации протокола связи с PCM
uint32_t prevRequest = 0; // таймер периодических запосов на PCM
uint16_t RequestPeriod = 3500; // периодичность запросов на PCM
byte header = 0; // состояние заголовка
bool NOanswer_timer = 0; // таймер контроля неответов от ЭБУ после подачи запросов
uint32_t prev_NOanswer=0; // таймер контроля неответов от ЭБУ после подачи запросов
// возможные варианты запросов на ЭБУ:
enum REQUEST {INIT, PID, DTCERASE, DTCREAD, PRESENT,};
#ifdef debugPCM
// текстовки запросов для отладки
char* textRequest[] = {"INIT", "PID_2101", "DTC_ERASE", "DTC_READ", "PRESENT",} ;
#endif
// сами запросы
byte PCM_Message_TX[][5] = {
{1, 0x81, 0,0,0}, // запрос инициализации
{2, 0x21,0x01, 0,0}, // запрос пид 2101
{3, 0x14,0xFF,0x00, 0}, // запрос на стирание ошибок
{4, 0x18,0x00,0xFF,0x00 }, // запрос на чтение ошибок
{1, 0x3E, 0,0,0}, // запрос присутствия
};
byte request = INIT; // переменная, показывающая какой запрос будем делать
static byte headerGAUGE = 0; // состояние заголовка сообщений щитка приборов
const byte bufsize = 150; // размер буфера принятого сообщения
byte MessageRx_PCM [bufsize] = {0}; // буфер принятого сообщения
//-------------------------------------------переменные бортовика
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 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
int IntTemp = 0; //Температура улицы
//все что касается топлива
float Fuel = 0; //остаток топлива
float Fuel2 = 0; float Fuel2_last = 1; //остаток мгновенного топлива байт 16 , датчика в баке
float FuelIGN = 0; // количество топлива в баке на момент включения зажигания
float fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
float FuelTrip = 0; float FuelTrip_last = 1; // количество литров топлива, израсходованное за один цикл включения зажигания
//все что касается километража
float kmAge = 0; //пробег, полученный со щитка приборов
float kmAgeIGN = 0; //пробег который был в момент включения зажигания
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
float kmTrip = 0; float kmTrip_last = 1; //пробег за один цикл включения зажигания
const int kmL = 50; // интервал, через который будет происходить обновление среднего расхода на 100км
// int km = 0; // переменная для расчетов
// const int kmeeprom = 15; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
// int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING = 0; int kmREFUELING_last = 1; // пробег до заправки на остатке топлива
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
//----------------------------------------------для экрана
#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>
//#include "Fonts/Chosence_Bold16pt7b.h";
#define MINPRESSURE 200
#define MAXPRESSURE 1000
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
UTFTGLUE myGLCD(0x1581,A2,A1,A3,A4,A0); //all dummy args
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; int h_last = 1;
float t; int t_last = 1;
bool Dvoet = 0;
bool reNew = 0;
#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0xF800
#define GREEN 0x07E0
//--------------------------------------датчики t
byte DSaddress[] = {0x28, 0xFF, 0xA6, 0x19, 0xA8, 0x15, 0x01, 0xD2};
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 26
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#include <OneWire.h>
#define ONE_WIRE_BUS 22
OneWire ds(ONE_WIRE_BUS);
void setup() {
uint16_t ID = myGLCD.readID();
if (ID == 0xD3D3) ID = 0x1581; // write-only shield
myGLCD.begin(ID);
myGLCD.InitLCD(3);
myGLCD.clrScr();
myGLCD.setTextSize(2);
//myGLCD.setFont(&Chosence_Bold16pt7b);
Wire.begin();
rtc.begin();
dht.begin();
//загрузка стартовой страницы
currentPage = '0';
drawHomeScreen();
//подсчет среднеарифметического усредненного расхода
float summar = 0;
for (int i = 0; i < 20; i+=4) {float summar_; EEPROM.get (i, summar_); summar +=summar_;}
L100SR_TFT = summar/5.00;
L100SR = L100SR_TFT;
/*
int summ=0;
for (int i = 0; i < 11; i++) summ += EEPROM.read(i);
L100SR_TFT = summ / 110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
*/
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить времая и дату, залить в ардуино. в скетче закоментировать
// обратно и залить еще раз, иначе каждый раз будет по новой выствлятся это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2019, 7, 2, 10, 48, 0));
#if defined debugPCM or defined debugGAUGE or defined debugTRIP
Serial.begin(115200);
#endif
K_LINE_PCM.begin(10400);
pinMode(TX_PCM, OUTPUT);
}
void loop()
{
curmillis = millis(); // снимок текущего времени
if (curmillis - prevRequest > RequestPeriod && header == 0 )
{
if (request == INIT) fastinit(); // при необходимости делаем переподключение к PCM
else {sendMessagePCM(request); // отправляем на PCM текущий запрос
if (request == PID) RequestPeriod = 600;
if (request == DTCERASE || request == DTCREAD) RequestPeriod = 2500;}
prevRequest = curmillis;
}
receivePCM (); // приём сообщений от PCM
receiveGAUGE (); // приём сообщений от щитка приборов
if (header == 0 && headerGAUGE == 0) {Menu ();}
if (curmillis - prevWatch > 4000) { Watch (); prevWatch = curmillis; h = dht.readHumidity(); t = dht.readTemperature();Temperature ();}
//if (curmillis - prevDvoet > 500) { if (!Dvoet) {myGLCD.setTextColor(WHITE); } else {myGLCD.setTextColor(BLACK); } myGLCD.print(":", 290, 5); prevDvoet = curmillis; Dvoet=!Dvoet;}
if (curmillis - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 285, 5);} else {myGLCD.print(" ", 285, 5);} prevDvoet = curmillis; Dvoet=!Dvoet;}
Trip ();
}// end loop
void fastinit() {
digitalWrite (TX_PCM, HIGH); // bus idle
delay(1500);
digitalWrite (TX_PCM, LOW); // first part fastinit (25 ms LOW)
delay(25);
digitalWrite (TX_PCM, HIGH); // second part fastinit (25 ms HIGH)
delay(25);
K_LINE_PCM.begin(10400);
sendMessagePCM(INIT); // send start communication message
}
void receivePCM () {
static uint32_t prevRESETheader=0; // таймер сброса сообщения, если данные оборвались посередине сообщения
static bool RESETheader_timer; // таймер сброса сообщения, если данные оборвались посередине сообщения
static byte noanswers = 0; // количество подряд неответов от ЭБУ
static byte message_size = 0; // размер тела сообщения
static byte j = 3; // инкремент
static byte n = 3; // количество старт байт
static byte crc =0; // байт контрольной суммы
if (K_LINE_PCM.available() ){
// первый старт байт
if (header == 0){ MessageRx_PCM[0]=K_LINE_PCM.read();
if (MessageRx_PCM[0]!=0xFF && bitRead (MessageRx_PCM[0],7)){header = 1; RESETheader_timer = 1; prevRESETheader = curmillis;
#ifdef debugPCM
Serial.print (F("Receive PCM: ")); printDebugRX(MessageRx_PCM[0]);
#endif
}
}
// второй старт байт
else if (header == 1){ MessageRx_PCM[1]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX (MessageRx_PCM[1]);
#endif
if (MessageRx_PCM[1]==DIAG_address){ header = 2;}
else {
#ifdef debugPCM
Serial.println(F(" PCM Message fail address"));
#endif
header = 0; RESETheader_timer = 0;}}
// третий старт байт
else if (header == 2){
MessageRx_PCM[2]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX (MessageRx_PCM[2]);
#endif
if (MessageRx_PCM[2]==PCM_address){ message_size = MessageRx_PCM[0]; prevRESETheader = curmillis;
if (MessageRx_PCM[0] !=0x80) {header = 4; bitWrite (message_size, 7 , 0);j=3;n=3;}
else {header = 3; j=4;n=4;}
if (message_size > bufsize) message_size = bufsize; crc = 0;}
else {header = 0;
#ifdef debugPCM
Serial.println(F("PCM Message fail address"));
#endif
RESETheader_timer = 0;}
}
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
else if (header == 3){
prevRESETheader = curmillis;
MessageRx_PCM[3]=K_LINE_PCM.read();
#ifdef debugPCM
printDebugRX(MessageRx_PCM[3]);
#endif
message_size = MessageRx_PCM[3];
if (message_size > bufsize) message_size = bufsize;
crc = 0; header = 4;
}
// пишем тело сообщения
else if (header == 4 && j< message_size+n+1) {
MessageRx_PCM[j] = K_LINE_PCM.read(); prevRESETheader = curmillis;
if (j<message_size+n) crc+= MessageRx_PCM[j]; // подсчёт КС
if (j==message_size+n) header = 5;
#ifdef debugPCM
printDebugRX(MessageRx_PCM[j]);
#endif
j++; }
}
// сообщение приняли, действуем
if (header == 5) {
#ifdef debugPCM
Serial.println();
#endif
NOanswer_timer = 0; noanswers = 0; // сбрасываем таймер контроля неответов
for(byte i = 0; i<n; i++) crc+=MessageRx_PCM[i]; // прибавляем к контрольной сумме старт байты
// если контрольная сумма верна:
if ( crc == MessageRx_PCM[message_size+n])
{
#ifdef debugPCM
Serial.print (F("Received message is OK! Checksum is correct!")); Serial.print (F(" ")); Serial.println (millis()); // Если КС совпала, тут чёнибудь нужное делаем
printDebugRX_CSgood(n);
#endif
if (MessageRx_PCM[n]==0xC1 && MessageRx_PCM[n+1]==0x6B && MessageRx_PCM[n+2]==0x8F) {
if (currentPage!=3) {request = PID; RequestPeriod = 70;} else request = PRESENT, RequestPeriod = 4000; prevRequest = curmillis; // receive good INIT
}
else if (MessageRx_PCM[n]==0x58) Troublecodes (n); // DTC
else if (MessageRx_PCM[n]==0x54 && MessageRx_PCM[n+1]==0xFF && MessageRx_PCM[n+2]==0x00){ request = PRESENT; RequestPeriod = 4000; prevRequest = curmillis;} // DTC are cleared
else if (MessageRx_PCM[n]==0x61 && MessageRx_PCM[n+1]==0x01) {dataVars(n) ; RequestPeriod = 70; prevRequest = curmillis; } // receive DataStream
}
// если контрольная сумма не совпала:
#ifdef debugPCM
else Serial.println("CRC fail!!!" );
#endif
message_size = 0; header=0; RESETheader_timer = 0; j=3; crc = 0;
}
// таймер сброса целостности сообщения (если данные оборвались посередине сообщения)
if (RESETheader_timer && curmillis - prevRESETheader > 200) {
#ifdef debugPCM
Serial.println(F("Message fail timeout"));
#endif
RESETheader_timer = 0; header = 0;}
// если нет ответа после запроса: +1 к счетчику неответов. Если накопилось 6 и более: делаем реинит.
if (request!=INIT && NOanswer_timer && curmillis - prev_NOanswer > RequestPeriod - RequestPeriod/10)
{
NOanswer_timer = 0; noanswers++;
if (noanswers>=6) { noanswers = 0; request = INIT; RequestPeriod = 3500;}
}
}// end receivePCM
void Troublecodes (const byte &n)
{
if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]==0x00){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 180, 145);
}
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]>0){
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx_PCM[n+8-7]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx_PCM[n+11-7+(i*3)],6) && bitRead(MessageRx_PCM[n+11-7+(i*3)],7)){ myGLCD.setTextColor(GREEN, BLACK);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx_PCM[n+11-7+(i*3)],7) && bitRead(MessageRx_PCM[n+11-7+(i*3)],6)) { myGLCD.setTextColor(RED, BLACK);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && !bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && !bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx_PCM[n+9-7+(i*3)],6) && bitRead(MessageRx_PCM[n+9-7+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx_PCM[n+9-7+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx_PCM[n+9-7+(i*3)]<=0x0F&&MessageRx_PCM[n+9-7+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}
if (nolA)myGLCD.print(String (MessageRx_PCM[n+9-7+(i*3)],HEX), 246, (75+y));
else myGLCD.print(String (MessageRx_PCM[n+9-7+(i*3)],HEX), 230, (75+y));
if (MessageRx_PCM[n+10-7+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx_PCM[n+10-7+(i*3)]<=0x0F&&MessageRx_PCM[n+10-7+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;}
if (nolB)myGLCD.print(String (MessageRx_PCM[n+10-7+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx_PCM[n+10-7+(i*3)],HEX), 262, (75+y));}}
request = PRESENT; RequestPeriod = 4000; prevRequest = curmillis;
}
void dataVars(const byte &n)
{
static float L100M_last = 1; //расход на 100 км измеренный за поездку
static float L100_last = 1; //мгновенный расход литров на 100км
static float LHor_last = 1; //мгновенный расход топлива литров в час
static float L100SR_TFT_last = 1; // самый средний из расходов на 100км, он выводится на экран
static int MAF_last = 1; //26,27 байты Sensor de flujo de aire en masa
static float BoostPres_last = 1; //28,29 байты Presión de refuerzo
static int RPM_last = 1; //32,33 байты Velocidad del motor
static int EGRmg_last = 1; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
static float BoostPresCom_last = 1;//38,39 байты Comando de presión de refuerzo
static int Speed_last = 1; //44,45 байты Velocidad del vehículo
static float DesaInjQua_last = 1; //50,51 байты Cantidad de inyección deseada
static float InjQua_last = 1; //52,53 байты Cantidad de la inyección
static float StaDaliv_last = 1; //54,55 байты Inicio de la entrega
static int PumpRPM_last = 1; //56,57 байты Velocidad de la bomba
static float EGRPul_last = 1; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
static float SolenPul_last = 1; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
static float SolenPre_last = 1; //70,71 байты Relación de impulsos Presión Electroválvula de presión
static float DesInj_last = 1; //72,73 байты Inyección deseada Inicio
static float ActInj_last = 1; //16,17 байты Inicio de la inyección real
static int TempAir_last = 1; //74,75 байты Temperatura del aire de admisión
static int Temp_last = 1; //14,15 байты Temperatura del refrigerante
static int TempOil_last = 1; //18,19 байты Temperatura del aceite del motor
static int TempFuel_last = 1; //58,59 байты Temperatura del combustible
static int IntTemp_last = 1; //Температура улицы
static float Fuel_last = 1; //уровень топлива в баке
//Barom = MessageRx_PCM[39];
MAF = ((MessageRx_PCM[n+22]*256)+MessageRx_PCM[n+23])/10;
BoostPres = ((MessageRx_PCM[n+24]*256)+MessageRx_PCM[n+25])/1000.0;
RPM = (MessageRx_PCM[n+35-7]*256)+MessageRx_PCM[n+36-7];
EGRmg = ((MessageRx_PCM[n+37-7]*256)+MessageRx_PCM[n+38-7])/10.0;
BoostPresCom = ((MessageRx_PCM[n+41-7]*256)+MessageRx_PCM[n+42-7])/1000.0;
Speed = ((MessageRx_PCM[n+47-7]*256)+MessageRx_PCM[n+48-7])/100;
DesaInjQua = ((MessageRx_PCM[n+53-7]*256)+MessageRx_PCM[n+54-7])/100.0;
InjQua = ((MessageRx_PCM[n+55-7]*256)+MessageRx_PCM[n+56-7])/100.0;
StaDaliv = ((MessageRx_PCM[n+57-7]*256)+MessageRx_PCM[n+58-7])/100.0;
PumpRPM = (MessageRx_PCM[n+59-7]*256)+MessageRx_PCM[n+60-7];
EGRPul = ((MessageRx_PCM[n+65-7]*256)+MessageRx_PCM[n+66-7])/100.0;
SolenPul = ((MessageRx_PCM[n+67-7]*256)+MessageRx_PCM[n+68-7])/100.0;
SolenPre = ((MessageRx_PCM[n+73-7]*256)+MessageRx_PCM[n+74-7])/100.0;
DesInj = ((MessageRx_PCM[n+75-7]*3)+(MessageRx_PCM[n+76-7])/100.0)+0.3;
ActInj = ((MessageRx_PCM[n+19-7]*3)+(MessageRx_PCM[n+20-7])/100.0)+0.3;
//TempAir = ((MessageRx_PCM[n+77-7]*26)-278)+MessageRx_PCM[n+78-7]/10.0;
//Temp = ((MessageRx_PCM[n+17-7]*26)-278)+MessageRx_PCM[n+18-7]/10.0;
//TempOil = ((MessageRx_PCM[n+21-7]*26)-278)+MessageRx_PCM[n+22-7]/10.0;
//TempFuel = ((MessageRx_PCM[n+61-7]*26)-278)+MessageRx_PCM[n+62-7]/10.0;
//ниже идут расчетные формулы более точные чем те что закоментированы выше
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
if (Speed!=0) L100 = (float)LHor*100.0/(float)Speed;
else L100 = 99;
int A = 0;
if (MessageRx_PCM[n+77-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+77-7]==0x0B || MessageRx_PCM[n+77-7]==0x0C) A = 278;
if (MessageRx_PCM[n+77-7]>=0x0D) A = 279;
double B = MessageRx_PCM[n+78-7]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx_PCM[n+77-7]*26)-A)+cel;
if (MessageRx_PCM[n+17-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+17-7]==0x0B || MessageRx_PCM[n+17-7]==0x0C) A = 278;
if (MessageRx_PCM[n+17-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+18-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx_PCM[n+17-7]*26)-A)+cel;
if (MessageRx_PCM[n+21-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+21-7]==0x0B || MessageRx_PCM[n+21-7]==0x0C) A = 278;
if (MessageRx_PCM[n+21-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+22-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx_PCM[n+21-7]*26)-A)+cel;
if (MessageRx_PCM[n+61-7]<=0x0A) A = 277;
if (MessageRx_PCM[n+61-7]==0x0B || MessageRx_PCM[n+61-7]==0x0C) A = 278;
if (MessageRx_PCM[n+61-7]>=0x0D) A = 279;
B = MessageRx_PCM[n+62-7]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx_PCM[n+61-7]*26)-A)+cel;
//----------------------------------------------------------
//страниц HOME
//----------------------------------------------------------
//myGLCD.setBackColor(RED);
myGLCD.setTextColor(WHITE, BLACK);
//myGLCD.setBackColor(RED);
if ((Speed != Speed_last) || reNew) {myGLCD.printNumI(Speed, 360, 7, 3); Speed_last=Speed;}
if (currentPage == '0') {
if ((LHor != LHor_last) || reNew) {myGLCD.printNumF(LHor, 1, 75, 40, '.',4); LHor_last=LHor;}
if ((L100 != L100_last) || reNew) {myGLCD.printNumF(L100, 1, 225, 40,'.',4 ); L100_last=L100;}
if ((L100M != L100M_last) || reNew) {myGLCD.printNumF(L100M, 1, 75, 75,'.',4 ); L100M_last=L100M;}
if ((L100SR_TFT != L100SR_TFT_last) || reNew) {myGLCD.printNumF(L100SR_TFT, 1, 225, 75,'.',4 ); L100SR_TFT_last=L100SR_TFT;}
if ((kmREFUELING != kmREFUELING_last) || reNew) {myGLCD.printNumI(kmREFUELING, 90, 110,3 ); kmREFUELING_last=kmREFUELING;}
//if (Fuel<53)
if ((Fuel != Fuel_last) || reNew) {myGLCD.printNumF(Fuel, 1, 225, 110,'.',4); Fuel_last=Fuel;}
//else myGLCD.print("MAX", 210, 110);
if ((kmTrip != kmTrip_last) || reNew) {myGLCD.printNumF(kmTrip, 1, 60, 145,'.',5); kmTrip_last=kmTrip;}
if ((FuelTrip != FuelTrip_last) || reNew) {myGLCD.printNumF(FuelTrip, 1, 210, 145,'.',5); FuelTrip_last=FuelTrip;}
if ((PumpRPM != PumpRPM_last) || reNew) {myGLCD.printNumI(PumpRPM, 230, 180,4); PumpRPM_last=PumpRPM;}
if ((RPM != RPM_last) || reNew) {myGLCD.printNumI(RPM, 230, 215,4); RPM_last=RPM;}
if ((Fuel2 != Fuel2_last) || reNew) {myGLCD.printNumF(Fuel2, 1, 10, 215,'.',4); Fuel2_last=Fuel2;}
if ((Temp != Temp_last) || reNew) {myGLCD.printNumI(Temp, 415, 40, 3); Temp_last=Temp;}
if ((TempOil != TempOil_last) || reNew) {myGLCD.printNumI(TempOil, 415, 75, 3); TempOil_last=TempOil;}
if ((TempFuel != TempFuel_last) || reNew) {myGLCD.printNumI(TempFuel, 415, 110,3); TempFuel_last=TempFuel;}
if ((IntTemp != IntTemp_last) || reNew) {myGLCD.printNumI(IntTemp, 415, 145 , 3); IntTemp_last=IntTemp;}
if ((t != t_last) || reNew) {myGLCD.printNumI(t, 415, 180, 3); t_last=t;}
if ((TempAir != TempAir_last) || reNew) {myGLCD.printNumI(TempAir, 415, 215, 3); TempAir_last=TempAir;}
reNew = 0;
}
//----------------------------------------------------------
//страниц INF1
//----------------------------------------------------------
if (currentPage == '1') {
if ((StaDaliv != StaDaliv_last) || reNew) {myGLCD.printNumF(StaDaliv,1, 385, 40,'.', 4); StaDaliv_last=StaDaliv;}
if ((DesInj != DesInj_last) || reNew) {myGLCD.printNumF(DesInj,1, 385, 75, '.', 4); DesInj_last=DesInj;}
if ((ActInj != ActInj_last) || reNew) {myGLCD.printNumF(ActInj,1, 385, 110,'.', 4); ActInj_last=ActInj;}
if ((DesaInjQua != DesaInjQua_last) || reNew) {myGLCD.printNumF(DesaInjQua,1, 385, 145,'.', 4);DesaInjQua_last=DesaInjQua;}
if ((InjQua != InjQua_last) || reNew) {myGLCD.printNumF(InjQua,1, 385, 180,'.', 4); InjQua_last=InjQua;}
if ((MAF != MAF_last) || reNew) {myGLCD.printNumI(MAF, 170, 215, 4); MAF_last=MAF;}
if ((h != h_last) || reNew) {myGLCD.printNumF(h, 1, 430, 215, 3); h_last=h;}
reNew = 0;
}
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
if ((BoostPres != BoostPres_last) || reNew) {myGLCD.printNumF(BoostPres,1, 400, 40,'.', 4); BoostPres_last=BoostPres;}
if ((BoostPresCom != BoostPresCom_last) || reNew) {myGLCD.printNumF(BoostPresCom,1, 400, 75,'.', 4); BoostPresCom_last=BoostPresCom;}
if ((EGRmg != EGRmg_last) || reNew) {myGLCD.printNumI(EGRmg, 400, 110, 4); EGRmg_last=EGRmg;}
if ((EGRPul != EGRPul_last) || reNew) {myGLCD.printNumF(EGRPul,1, 400, 145,'.', 4); EGRPul_last=EGRPul;}
if ((SolenPul != SolenPul_last) || reNew) {myGLCD.printNumF(SolenPul, 1, 400, 180,'.', 4); SolenPul_last=SolenPul;}
if ((SolenPre != SolenPre_last) || reNew) {myGLCD.printNumF(SolenPre, 0, 400, 215,'.', 4); SolenPre_last=SolenPre;}
reNew = 0;
}
//reNew = 0;
}
void sendMessagePCM(const byte &command)
{
#ifdef debugPCM
Serial.print (F("Send request ")); Serial.print (textRequest[command]); Serial.print (F(" to PCM ")); Serial.println (millis());
#endif
if (command != INIT) {NOanswer_timer = 1; prev_NOanswer = curmillis;} //т.к. сейчас будем делать запрос, то запускаем таймер контроля неответов
byte size = PCM_Message_TX[command][0];
const byte siZe = size+4;
byte Mes[siZe];
byte Checksum = 0;
for(byte i=0; i<siZe; i++) {
if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
if (i==1) Mes[i] = PCM_address;
if (i==2) Mes[i] = DIAG_address;
if (i==3) {for (byte t=1; t<size+1; t++ ) {
Mes[i]=PCM_Message_TX [command][t];
Checksum+=Mes[i] ;
K_LINE_PCM.write (Mes[i]);
if (command == INIT) delay (5); else delay (1);
K_LINE_PCM.read();
i++;}}
if (i!=siZe-1) Checksum+=Mes[i];
else Mes[i] = Checksum;
K_LINE_PCM.write (Mes[i]);
if (command == INIT) delay (5); else delay (1);
K_LINE_PCM.read();
}
}// end sendMessagePCM
void Trip ()
{
static uint32_t prevRefueling = 0;
if (curmillis - prevRefueling>1000)
{ static float rashod [60]={0};
static byte yacheyka_numer = 0;
rashod[yacheyka_numer] = L100;
if (yacheyka_numer == 59)
{
//-----------------расчет среднего расхода
float km_prev = 0;
EEPROM.get (130, km_prev); // считываем из еепром пробег прошлого измерения каждую минуту
float kmTrip_refuel = 0;
if (kmAge>km_prev) kmTrip_refuel = kmAge - km_prev;
if (kmAge<km_prev) kmTrip_refuel = 2000 - (km_prev - kmAge);
if (kmAge==km_prev) kmTrip_refuel = 0;
if (kmTrip_refuel >=kmL) {
float l_prev = 0;
EEPROM.get (140, l_prev); // считываем из еепром уровень топлива прошлого измерения
if (l_prev-Fuel > 0) L100SR = ((float)(l_prev-Fuel)*100.00)/(float)kmL;
EEPROM.put (140, Fuel); // записываем в еепром уровень топлива текущего измерения
EEPROM.put (130, kmAge); // записываем в еепром пробег текущего измерения
byte n_eeprom = EEPROM.read (150); // в ячейке 150 хранится № текущей ячейки для записи расхода, чтобы где остановился при выкл питания, от туда и продолжил
EEPROM.put(n_eeprom, L100SR);
n_eeprom+=4; if (n_eeprom>16) n_eeprom=0;
EEPROM.write (150,n_eeprom);
float summar = 0.0;
for (int i = 0; i < 20; i+=4) {float summar_=0.0; EEPROM.get (i, summar_); summar +=summar_;}
L100SR_TFT = summar/5.00;
kmREFUELING=Fuel*100.00/L100SR_TFT; //расчет остатка км в баке
}
} // end of 1 minuts
//---------------расчёт пробега и расхода за поездку
if (yacheyka_numer == 5) {
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;
}}
yacheyka_numer++; if (yacheyka_numer>59) yacheyka_numer = 0;
prevRefueling = curmillis;
}
}
/*
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;
// тут считаем среднеарифметический усредненного расхода из ячеек еепром
int summ = 0;
for (int i = 0; i < 11; i++) summ += EEPROM.read(i);
L100SR_TFT = summ / 110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 25;}
// ниже цикл считает расход топлива за пробег, указанный в переменной 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); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
byte 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);
#ifdef debugTRIP
Serial.println (" I am heer: if (kmTrip-km>kmL) {} ");
Serial.print (" L100SR = "); Serial.print (L100SR) ; Serial.println (" L/100km");
Serial.print (" kmREFUELING = "); Serial.print (kmREFUELING) ; Serial.println (" km");
#endif
}
#ifdef debugTRIP
Serial.print (" FuelTrip = "); Serial.print (FuelTrip); Serial.println (" L");
Serial.print (" kmTrip = "); Serial.print (kmTrip); Serial.println (" km");
Serial.print (" L100SR_TFT = "); Serial.print (L100SR_TFT); Serial.println (" L/100km");
#endif
}}
*/
void receiveGAUGE () {
static uint32_t prevRESETheaderGAUGE=0; // таймер сброса сообщения, если данные оборвались посередине сообщения
static bool RESETheader_timerGAUGE; // таймер сброса сообщения, если данные оборвались посередине сообщения
static uint32_t prevNoconnect = 0; // таймер периодической проверки наличия связи со щитком приборов
static byte NoconnectsGAUGE = 0 ; // счетчик неответов от щитка приборов
static byte message_sizeGAUGE = 0; // размер тела сообщения
static byte jGAUGE = 3; // инкремент
static byte nGAUGE = 3; // количество старт байт
static int ChecksumGAUGE =0; // байт контрольной суммы
static byte InitGauge = 0; // автомат состояния инита щитка приборов
const byte bufsizeG = 100; // размер буфера принятого сообщения
static byte MessageRx_GAUGE [bufsizeG] = {0}; // буфер принятого сообщения
byte PIDgauge[] = {0x02,0x11,0x00,0x13}; // запрос параметоров щитка приборов
if (K_LINE_GAUGE.available() ){
// первый старт байт
if (headerGAUGE == 0){ MessageRx_GAUGE[0]=K_LINE_GAUGE.read();
if ((InitGauge ==1 && MessageRx_GAUGE[0]==0x55) || (InitGauge ==2 && MessageRx_GAUGE[0]!=0xFF && MessageRx_GAUGE[0]!=0x7F)
|| (InitGauge ==3 && MessageRx_GAUGE[0]==0x23)
)
{headerGAUGE = 1; RESETheader_timerGAUGE = 1; prevRESETheaderGAUGE = curmillis;
#ifdef debugGAUGE
Serial.print (F("Receive GAUGE: ")); printDebugRX(MessageRx_GAUGE[0]);
#endif
}
}
// второй старт байт
else if (headerGAUGE == 1){ MessageRx_GAUGE[1]=K_LINE_GAUGE.read();
#ifdef debugGAUGE
printDebugRX (MessageRx_GAUGE[1]);
#endif
if ( (InitGauge ==1 && MessageRx_GAUGE[1]==0x52) || (InitGauge ==2 && (MessageRx_GAUGE[1]==0xA0 || MessageRx_GAUGE[1]==0xF0))
|| (InitGauge == 3 && MessageRx_GAUGE[1]==0xA1)){ headerGAUGE = 2;}
else {
#ifdef debugGAUGE
Serial.println(F(" GAUGE Message fail address"));
#endif
headerGAUGE = 0; RESETheader_timerGAUGE = 0;}}
// третий старт байт
else if (headerGAUGE == 2){
MessageRx_GAUGE[2]=K_LINE_GAUGE.read();
#ifdef debugGAUGE
printDebugRX (MessageRx_GAUGE[2]);
#endif
if ((InitGauge ==2 && (MessageRx_GAUGE[2]==0x48 || MessageRx_GAUGE[2]==0x55 || MessageRx_GAUGE[2]==0xAA)) || (InitGauge == 3 && MessageRx_GAUGE[2]==0x04)){ message_sizeGAUGE = MessageRx_GAUGE[0]-2; prevRESETheaderGAUGE = curmillis;
headerGAUGE = 4; jGAUGE=3; nGAUGE=3;
if (message_sizeGAUGE > bufsizeG) message_sizeGAUGE = bufsizeG; ChecksumGAUGE = 0;}
else if (InitGauge ==1 && MessageRx_GAUGE[2]==0x80) {InitGauge = 2; K_LINE_GAUGE.write(0x7F); delay (2); K_LINE_GAUGE.read(); headerGAUGE = 0; RESETheader_timerGAUGE = 0;
#ifdef debugGAUGE
Serial.println ("Gauge INIT is good!");
#endif
}
else {headerGAUGE = 0;
#ifdef debugGAUGE
Serial.println(F("GAUGE Message fail address"));
#endif
RESETheader_timerGAUGE = 0;}
}
// пишем тело сообщения
else if (headerGAUGE == 4 && jGAUGE< message_sizeGAUGE+nGAUGE+1) {
MessageRx_GAUGE[jGAUGE] = K_LINE_GAUGE.read(); prevRESETheaderGAUGE = curmillis;
if (jGAUGE<message_sizeGAUGE+nGAUGE-1) ChecksumGAUGE+= MessageRx_GAUGE[jGAUGE]; // подсчёт КС
if (jGAUGE==message_sizeGAUGE+nGAUGE) headerGAUGE = 5;
#ifdef debugGAUGE
printDebugRX(MessageRx_GAUGE[jGAUGE]);
#endif
jGAUGE++; }
}
// сообщение приняли, действуем
if (headerGAUGE == 5) {
#ifdef debugGAUGE
Serial.println();
#endif
for(byte i = 0; i<nGAUGE; i++) ChecksumGAUGE+=MessageRx_GAUGE[i]; // прибавляем к контрольной сумме старт байты
int ChecksumG = ( ( unsigned int )MessageRx_GAUGE[message_sizeGAUGE+nGAUGE-1] << 8 ) | MessageRx_GAUGE[message_sizeGAUGE+nGAUGE]; // парсинг контрольной суммы из 2 последних байт
// если контрольная сумма верна:
if ( ChecksumGAUGE == ChecksumG)
{ NoconnectsGAUGE = 0; // сбрасываем на 0 отсутствие связи с панелью
#ifdef debugGAUGE
Serial.print (F("Received message is OK! Checksum is correct!")); Serial.print (F(" ")); Serial.println (millis()); // Если КС совпала, тут чёнибудь нужное делаем
#endif
if (MessageRx_GAUGE[1]== 0xA0 && MessageRx_GAUGE[2]== 0x48) {
#ifdef debugGAUGE
Serial.println ("ID panel receive! Send request PIDGauge");
#endif
InitGauge = 3;
for (byte i=0; i<sizeof(PIDgauge); i++) { K_LINE_GAUGE.write (PIDgauge[i]); delay (1); K_LINE_GAUGE.read();}
}
if (MessageRx_GAUGE[1]== 0xF0 && (MessageRx_GAUGE[2]== 0xAA || MessageRx_GAUGE[2]== 0x55)) {
#ifdef debugGAUGE
Serial.println ("receive present from Gauge. I send PID to Gauge");
#endif
InitGauge = 3;
for (byte i=0; i<sizeof(PIDgauge); i++) { K_LINE_GAUGE.write (PIDgauge[i]); delay (1); K_LINE_GAUGE.read();}
}
if (MessageRx_GAUGE[1]== 0xA1 && MessageRx_GAUGE[2]== 0x04) {
#ifdef debugGAUGE
Serial.println (" receive Datastream Gauge!");
#endif
Fuel2 = MessageRx_GAUGE[nGAUGE + 16]/2.0;
if (!flagFuelIGN) { Fuel = MessageRx_GAUGE[nGAUGE + 16]/2.0; kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;} //стартовая запись литров в баке для подсчета затраченных литро
else Fuel = MessageRx_GAUGE[nGAUGE + 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 = (MessageRx_GAUGE[nGAUGE + 23]+(MessageRx_GAUGE[nGAUGE + 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;}}
#ifdef debugTRIP
Serial.print (" Fuel = "); Serial.print (Fuel); Serial.println (" L");
Serial.print (" kmAge = "); Serial.print (kmAge); Serial.println (" km");
#endif
}
}
// если контрольная сумма не совпала:
#ifdef debugGAUGE
else Serial.println("CRC fail!!!" );
#endif
message_sizeGAUGE = 0; headerGAUGE=0; RESETheader_timerGAUGE = 0; jGAUGE=3; ChecksumGAUGE = 0;
}
// таймер сброса целостности сообщения (если данные оборвались посередине сообщения)
if (RESETheader_timerGAUGE && curmillis - prevRESETheaderGAUGE > 300) {
#ifdef debugGAUGE
Serial.println(F("Message fail timeout"));
#endif
RESETheader_timerGAUGE = 0; headerGAUGE = 0;}
if (curmillis - prevNoconnect > 500) {NoconnectsGAUGE ++ ; if (NoconnectsGAUGE>=8){
#ifdef debugGAUGE
Serial.println (F(" Connect GAUGE failed!!! ")) ;
#endif
NoconnectsGAUGE = 0 ;InitGauge = 0 ; } prevNoconnect = curmillis; }
InitBusGAUGE (InitGauge);
}// end receiveGAUGE
void InitBusGAUGE (byte &InitGauge)
{
uint32_t prevInitbusGauge = 0; // таймер для инита щитка приборов
if (InitGauge == 0){
#ifdef debugGAUGE
Serial.println ("Send startsession - address Gauge");
#endif
K_LINE_GAUGE.end();
pinMode(TX_gauge, OUTPUT);
digitalWrite (TX_gauge, HIGH); // BUS IDLE
InitGauge = 5; prevInitbusGauge = curmillis;
}
if (InitGauge == 5 && curmillis - prevInitbusGauge>1500) {InitGauge = 6;} // BUS IDLE
if (InitGauge == 6)
{
byte boudrate = 1000/BAUD;
digitalWrite (TX_gauge, LOW); delay (boudrate); // старт бит
for (byte i=0; i<8; i++){digitalWrite (TX_gauge, bitRead(addressGUAGE, i)); delay (boudrate);} // биты тела адреса
digitalWrite (TX_gauge, HIGH); delay (boudrate); // стоп бит
K_LINE_GAUGE.begin(9600);
InitGauge = 1;
}
}
#if defined debugPCM or defined debugGAUGE
void printDebugRX (const byte &inbyte) {if (inbyte<=15) Serial.print(F("0")); Serial.print (inbyte, HEX); Serial.print (F(" "));}
#endif
#ifdef debugPCM
void printDebugRX_CSgood(const byte &n){
if (MessageRx_PCM[n]==0xC1 && MessageRx_PCM[n+1]==0x6B && MessageRx_PCM[n+2]==0x8F) {Serial.println (F(" Initialization OK!!!!")); }
else if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1]==0x00) {Serial.println (F(" NO DTC "));}
else if (MessageRx_PCM[n]==0x58 && MessageRx_PCM[n+1] >0x00) {Serial.println (F(" DTC is found!"));}
else if (MessageRx_PCM[n]==0x54 && MessageRx_PCM[n+1]==0xFF && MessageRx_PCM[n+2]==0x00){Serial.println (F(" DTC CLEARED "));}
else if (MessageRx_PCM[n]==0x61 && MessageRx_PCM[n+1]==0x01) {Serial.println (F(" Receive PCM DATAstream"));}}
#endif
void Menu () {
TouchHOME();
if (currentPage == '0') {
TouchINF1();
TouchINF2();
TouchCHECK(); }
if (currentPage == '1') {
TouchINF2();
TouchCHECK(); }
if (currentPage == '2') {
TouchINF1();
TouchCHECK(); }
if (currentPage == '3') {
TouchREAD();
TouchERASE(); }}
void drawHomeScreen() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(80,178,80,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/L/A", 10, 180);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("OIL C", 300, 75);
myGLCD.print("FUEL C", 300, 110);
myGLCD.print("FUERA C", 300, 145);
myGLCD.print("DENTRO C", 300, 180);
myGLCD.print("INTAIR C", 300, 215);
//myGLCD.setTextColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("INF 1", 55, 270);
myGLCD.drawRoundRect (175, 255, 305, 310);
myGLCD.print("INF 2", 215, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
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.setTextColor(RED);
myGLCD.drawRoundRect (175, 255, 305, 310);
myGLCD.print("INF 2", 215, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//-------------------------------------------------
void drawscreen_two() {
line() ;
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии и текста красный
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.setColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("INF 1", 55, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("CHECK", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 7);
myGLCD.print("Km/h", 410, 7);
reNew = 1;
Watch ();
}
//----------------------------------------------------------------------------
void drawscreen_three() {
//myGLCD.print(":", 290, 5);
myGLCD.print("/", 115, 7);
myGLCD.print("/", 160, 7);
myGLCD.setTextColor(RED, BLACK); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
//myGLCD.setTextColor(RED);
myGLCD.drawRoundRect (15, 255, 145, 310);
myGLCD.print("ERASE", 55, 270);
myGLCD.drawRoundRect (335, 255, 465, 310);
myGLCD.print("READ", 365, 270);
myGLCD.drawRoundRect (1, 1, 77, 37);
myGLCD.print("HOME", 10, 5);
reNew = 1;
Watch ();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//кнопки тач . координаты и переходы
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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.drawRoundRect (1, 1, 77, 37);
currentPage = '0';
request = PID; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawHomeScreen();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (15, 255, 145, 310);
currentPage = '1';
request = PID; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawscreen_one();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (175, 255, 305, 310);
currentPage = '2';
request = PID; RequestPeriod = 600; prevRequest = curmillis; // на PCM в этом окне посылается запрос текущих параметров
myGLCD.clrScr();
drawscreen_two();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (335, 255, 465, 310);
currentPage = '3';
// request = DTCREAD; RequestPeriod = 10; prevRequest = curmillis; // на PCM в этом окне посылается запрос чтения ошибок
myGLCD.clrScr();
drawscreen_three();
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (335, 255, 465, 310);
request = DTCREAD; RequestPeriod = 300; prevRequest = curmillis; // на PCM при нажатии этой кнопки посылается запрос чтения ошибок
x = 0;
y = 0;
p.z = 0;}}}
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.drawRoundRect (15, 255, 145, 310);
request = DTCERASE; RequestPeriod = 300; prevRequest = curmillis; // на PCM при нажатии этой кнопки посылается запрос удаления ошибок
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 180, 145);
x = 0;
y = 0;
p.z = 0;}}}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
//myGLCD.setTextColor(RED); // цвет линии красный
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 minut = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
int Year = now.year();
static int minut_last;
static int hour_last;
static int mon_last;
static int date_last;
static int Year_last;
myGLCD.setTextColor(WHITE, BLACK); //белый цвет цифры
if (date != date_last || reNew){ myGLCD.printNumI(date, 85, 7, 2, '0'); date_last = date; }
if (mon!=mon_last || reNew){myGLCD.printNumI(mon, 130, 7, 2, '0'); mon_last = mon; }
if (Year!=Year_last || reNew) { myGLCD.printNumI(Year, 175, 7); Year_last = Year; }
if (hour!=hour_last || reNew){ myGLCD.printNumI(hour, 255, 7, 2, '0'); hour_last = hour; }
if (minut!=minut_last || reNew ){ myGLCD.printNumI(minut, 300, 7, 2, '0'); minut_last = minut; }
}
void Temperature () {
static boolean p=0; // флаг работы: запрос температуры или её чтение
p=!p;
if (p) {ds.reset(); // сброс шины
ds.write(0xCC); // обращение ко всем датчикам
ds.write(0x44); // начать преобразование (без паразитного питания)
}
else {
int Temper_= 20; byte buff[9];
ds.reset();
ds.select(DSaddress);
ds.write(0xBE); // Read Scratchpad (чтение регистров)
for (byte j = 0; j<9; j++) buff[j]= ds.read(); //читаем все 9 байт от датчика
ds.reset();
if (OneWire::crc8(buff, 8) == buff[8]){ // если контрольная сумма совпадает
Temper_ = buff[0] | (buff[1]<<8); // читаем температуру из первых двух байт (остальные были нужны для проверки CRC)
Temper_ = Temper_ / 16;
if (Temper_ < 150 && Temper_ > -50 && Temper_ !=85 && Temper_!=-127) IntTemp = Temper_;
}
}
}
Макс эти строки делают зависимость от полного суточного пробега 2000?
if (kmAge>km_prev) kmTrip_refuel = kmAge - km_prev;
if (kmAge<km_prev) kmTrip_refuel = 2000 - (km_prev - kmAge);
Komandir .Помогите ещё раз. В строке 961 я поставил 4195 ,т.е стоимость 41,95 р. за литр. в строке 4073 поставил 2:1. Поставил на автомобиль свой БК. Всё нормально ,всё что нужно показывает,только стоимость поездки делит на 10. Литр потратил должен показывать 41,95, а он выдаёт Р4,19 .Где в коде изменить ,чтобы показывало правильно. Или просто в строке 961 поставить 41950?
Попробовал это не то.А вот когда пробовал удалять конвертацию из галлонов в литры и наоборот, чтобы совсем убрать СТРОКА 2679 и так далее .Вместо -$1,325+ получилось -10,0какой то символ+ .Где то здесь наверное нужно изменять.GasConst 3355 это я понял для расчёта расхода топлива. Ещё такой вопрос,здесь контрастность меняется по шим сигналу.Где в коде можно увеличить частоту ,чтобы мерцание было меньше.Спасибо.
Или где то здесь.
я вроде нашел косяк. Для того, чтобы данные на экран обновлялись только при их изменении, ты ввёл переменные с постфиксом _last
Дак вот в том числе и для переменной Fuel ты сделал Fuel_last для такого вывода на экран.
А переменная Fuel_last у нас уже была и использовалась в бортовике для расчёта среднего расхода и расстояния до заправки. А при выводе на экран ты эту переменную портишь, поэтому все расчёты в гавно.
исправил
код похож, конечно, на говнокод с ужасным количеством глобальных переменных, потому что я писал его очень давно и не шарил толком, поэтому такие косяки сейчас и возникают.
понял, блин у меня была такая мысль что может last-ы чета мутят . но боялся уже чета трогать, чтобы не напортачить. уже на следующей недели в понедельник проверю на работе. отпишусь, спасибо
С мерцанием разобрался.Поставил конденсатор на 2 и 3 пин дисплея.Где по умолчанию стоит стоимость за литр бензина так и не могу найти в коде.
Сергей, что именно имеется ввиду про стоимость топлива? Проблема непонятна. Сними видео
Он ищет как задать стоимость топлива в рублях для расчетов, вместо долларов. Типа сколько рублей потрачено за поездку или на данный момент сколко стоит его пройденый путь, типа того
viki13viki да так и есть.Не могу в коде найти где стоимость устанавливается с одного доллара.Стоит в меню -$1.234+.Хочу сразу переделать ,чтобы с -P40.00+ устанавливалось.По одной сотой прибавлять очень долго.Стоимость записывается в память.В принципе не нужная функция ,только ради интереса.Спасибо ,что отвечаете.
Попробуй без сотых поставить, 40 что получится?
В меню я могу поставить -$40.000+ .Выставить кнопкой, долго нажимая, с одного доллара. Я не могу в коде найти почему по умолчанию стоит стоимость за 1литр от одного доллара (1.000 с тысячными), где это изменить, и чтобы ещё тысячные убрать до сотых. Бак по умолчанию в настройках стоит 45 литров, и все остальные настройки уже прописаны, где они в коде подскажите пожалуйста.
В коде где у тебя доллар 1.234 оставь 1 без сотых. Попробуй так
Так в том то и дело,что я не могу понять где в коде этот доллар стоит. И все остальные начальные настройки. Пример-(Бак в литрах уже стоит по умолчанию 45литров.)
последняя моя догадка, дальше я бессилен. Мне все таки кажется что задается именно здесь
/**************************/
/* GASOLINE ENGINE CONFIG */
/**************************/
// [CONFIRMED] For gas car use 3355 (1/14.7/730*3600)*10000
#define GasConst 3355
#define GasMafConst 107310 // 14.7*730*10
тебе нужно заменить 3355 на 42250 что значит у низ 3.355 и у тебя 42.25
когда заменил на 43350 изменилась цена с 1.234 доллара на другое чтото?
и в этой строке cents = fuel * params.gas_price / 1000; //now have $$$$cc
попробуй 1000 заменить на 100, станет ли цена 12.34
я одного не могу найти где прописан params.gas_price
и еще смотри здесь вроде конвертация в галоны но может от нее и пляшет
в галонах цена 3.785 и прога конвертирует в бензин и выходит 1.234 доллара
378L это у них 3.785 доллара из которого выходит 1.234 доллара, примерно половина. поиграй с этим значением. поставь например 2110L что есть половина 4225 . там в двух местьах нудно поменять в коде выше.
если нет, то значит, что в другом месте нужно менять. если да то эксперементируй. дальше я пас, я безпонятия.
Sergei H. 961 строка - начальная цена (умноженная на 1000 вроде).
Строки с 951 по 1004 задают начальные данные.
Вижу также запись и чтение в EEPROM - видимо есть возможность настроить с кнопок и сохранить настройки, а потом уже с них и стартовать.
Шаг настройки с кнопок надо менять в строках с 4033 по 4067.
О Командир :). Я пытаюсь помочь но из мен програмист еще тот, могу только догадывтася. в 961 строке это
1090, чет не поляшет
. думпешь что это типа стоимость литра 1.9 долларов, знвяит ему нужно подставить 40025 это 40.25 в рублях?
viki13viki ты методом тыка пробуешь ... 5000+ строк таким методом до старости можно гонять.
Я краем глаза глянул логику скетча и нашел где задаются начальные данные. А вот коэффициент 1000 или 100 пока не увидел ...
вот вроде cents = fuel * params.gas_price / 1000; //now have $$$$cc
просто пытаюсь помчь как могу, метод тыка долгий с таким кодом я знаю.
Спасибо всем.Komandir с шагом настройки разобрался,теперь на много проще.Постоянные я так понял сразу записываются в память.После заливки кода как изменишь,остаются в памяти, после можно только подстраивать.Точно снёс память смог изменять строки 951 по 1004. Теперь вопрос где изменить в коде чтобы было 42,00 рубля а не 42,000. Строка 961 это стоимость топлива значит у меня было 1,090 доллара.Это я viki13viki в заблуждение ввёл извините.
4073 3:1 на 2:1 или "fuelUnits > 999 ? 3 : 1" на 2
Макс залил 2053. Нужен прогон. Сегодня вечером и звтра утром пргоню и утром отпишусь.
Макс выехал домой , километров в баке 0 и средний расход 0.0. Надеялся что пробег даст первые записи и все будет норм. проехал, через 10 км показало километры в баке, средний расход 0.0. Утром включаю зажигание, литры в баке 0 и средний расход 0.0. Поехал на работу. Прогнал 30 км, как всегда после 10 км показало километры в баке, средний расход так и остался 0. Заглушил, включил, километров в баке 0 и средний расход 0.0. Вот такая вот картина.
тогда на экран что-нибудь выведи, в строках 604-610 и в строках 614-635, чтобы узнать заходит ли сюда программа.
в 611 строке выведи на экран значение переменной L100SR_TFT
между 615 и 614 выведи L100SR
Макс по порядку. 604-610 это у нас расчет L100SR_TFT он у нас на экране и он всегда в ноль. 614-631 это у нас L100SR (может не работает), остатки километров через 10 км начинает показывать (работает если в конце формулы 6.7 а не L100SR_TFT, не помню или с L100SR_TFT работало или нет, сегондня проверю), а вот в строчках 625-628 от туда и "продолжаем последнее значение данных" (не работает, всегда с нуля начинает). Значит заходит и считает , видно по формуле киллометров в баке если стоит 6.7, но чтото не чиатет. Остается проверить L100SR ну и на всякий случай выведу там же и L100SR_TFT, ща выведу их между 604-631, узнаем или заходит сюда прога и работает ли они. Еще одно увидел что L100SR_TFT его расчеты прописаны два раза в setup 174-179 и в voidtrip 606-610 (не знаю, может так нужно.....). Завтра скажу че да как.
Вообщем вывел я это
myGLCD.printNumF(L100SR, 1, 10, 215,'.',4);
if ((L100SR_TFT != L100SR_TFT_last) || reNew) {myGLCD.printNumF(L100SR_TFT, 1, 225, 75,'.',4 ); L100SR_TFT_last=L100SR_TFT;}
между 604-631 на экране не отображеются эти данные, думаешь значит что не заходит сюда? тогда почму если в формуле километров в баке, которая находится межу этимх строк ставить 6.7 вместо L100SR_TFT расчет ведется? значит заходит, хз.
залей такой скетч для чисти еепром, покажи что он в сериал выведет.
Потом я исправил 2053. заливай его после чистки еепром. По идее средний расход сразу должен показать 25.5. Потом начать уменьшаться раз в 15 км. и L100SR где нибудь выведи. От него средний ведь считается в ячейки еепром. Нужно посмотреть как он меняется раз в 10 км. Может ты координаты корявые при выводе сделал. Сделай маленький скетч. Проверь как эти строки на экран выводят, работает ли вывод этих строк
у тебя с такими же координатами как ты сделал вывод L100SR что то другое на экран выводится:
if ((Fuel2 != Fuel2_last) || reNew) {myGLCD.printNumF(Fuel2, 1, 10, 215,'.',4); Fuel2_last=Fuel2;}
а оно ведь часто обновляется, вот и перекрывает
залил очиску вывод
255 255 255 255 255 255 255 255 255 255 255 255 0
залил скетч 2053, да средний показал 25.5
вывел L100SR вместо актуального топлива, поглядим после пробега пока 0.0
остальное утром скажу после пробега
Fuel2 это актуальное топливо в баке.
ок
а вообще слишком маленькие интервалы (10км) для измерения . Ведь при расходе менее 10л/100км, за этот отрезок менее 1 литра израсходуется, а значит если десятые литра откинуть, то израсходаванных литров будет 0. Соответственно и средний расход поэтому 0. нужно делать бОльшие интервалы, хотя бы раз в 30 км.
ещё раз поправил 2053, так как при расчёте L100SR использовалась промежуточная переменная fuel_last, а она была типа int , т.е. без учёта десятых литра. а при маленьких отрезках измерения (10км) тут десятые очень важны. Исправил это
Расход надо считать по количеству импульсов на форсунке.
Понял, принял. Перезалью сейчас.
Расход надо считать по количеству импульсов на форсунке.
такой расход есть и считается. Это мгновенный расход
можно ещё попробовать новый подход. Заливаем этот скетч для чистки еепром. Там ставим текущие данные с панели.
здесь применил расчёт среднего расхода с измерениями на больших дистанциях в 50км для увеличения точности. А данные сохраняются в еепром ,т.к. за одну поездку не всегда получается проезжать 50 км, поэтому при старте МК измерения продолжатся с последнего момента. Т.е. проехали 30 км, в следующий раз он и считает уже с 30 км, т.е. нужно ещё 20 проехать для того, чтобы произошло измерение.
а расчёт пробега до заправки сделан по мгновенному расходу с помощью интегрирования (среднеарифметическое между 60 измерениями, которые делаются раз в 15 сек). Т.е. этот параметр обновляется раз в 15 минут.
звучит круто. значит заливаю первый, подставив данные, и потом заливаю второй и сегодня прокатить?
сделал. поставил 1744 км, 12 литров, и 6.7 расход, залил. Потом залил второй, на экране показало средний 6.7 , и расчитало бак на 164 км, актуальный расход 99.0. завтра отпишу после пробега
нашёл пару ошибок, исправил 2083.
я так понимаю по 2083 до исправления ошибок нет смысла отчитыватся. Но тем не мение. Вчера пройдено около 35км. Со старта расчет километров в баке был реальным 170 км, через киллометров 15 стало 23 км в баке и так аж до дома. Средний со старта так и остался 6.7 л на 100 км. Утром выехал сново со старта было км в баке реально спустя 11-15 км сново показал занижено гдето 20 с чемто. Средний оставался 6.7 л на 100 км. Проехал 20 км заехал на заправку. заправил бак на полную. Завел и сбросил суточный на ноль, и сразу показало что я 200 км уже проехал, не стал заморачиватся глушить, поехал дальше. Км в баке показало на 805 км. Доезжая до работы пройдя километров 6 , вдруг средний расход сменился на 5.4 л на 100 км, км в баке так и остались на 805 км. На работе заглушил и включил показало средний 5.4 и км в баке 1007 км. Может какието выводы можно из этого сделать. Сегодня залью подправленый 2083, если я сейчас его залью 10 км хватит для теста? учитываю что буду гонять по кругу большому с поворотами и маленькими спусками и подьемчиками учитывая что будет сильная болтанка в баке, это даст какойто результат для проверки? или лучше уже вечером домой сделать нормальный прогон?
пробег до заправки очень коряво должен был показывать, в этом и была ошибка , я там формулу не ту написал. так что тут нечему удивляться. При заправке не надо скидывать суточный на ноль. Этим самым ты вводишь в ступор бортовик. Через 2000 км на ноль он сам безболезненно должен перепрыгивать . Если заправился , по идее один из расчетов среднего расхода просто должен пропуститься , т.е. следующие 50 км после заправки средний расход будет без изменений.
Я понял. Но при заправки полного бака я всегда скидываю суточный, привычка, так как знаю что до загорания лампочки приезжаю где-то 770 км. Привычка.
аа, ну тогда надо и на бортовике делать кнопку сброса этих значений, а то не корректно будет одно измерение, от слова совсем. Логика в новом скетче такая.
Расчёт среднего расхода происходит раз в 50км при отсутствии заправки и сброса суточного пробега.
Расчёт пробега до заправки делается так: в течение одной минуты раз в секунду записывается мгновенный расход. Итого имеем 60 значений. Считаем среднее арифметическое. Далее это среднее опять записывается в массив из 20 значений. По истечении записи в этот массив (двадцатое значение) считается опять среднеарифметический расход на сотню и уже здесь и считается пробег до заправки. Таким образом пробег до заправки обновляется раз в 20 минут . Соответственно если мы стоим и не едем, то расход записывается по 99 л/100км. Поэтому в пробках расстояние до заправки будет снижаться.
Не знаю на сколько такой алгоритм будет адекватен.
Раньше я всегда так делал, но у меня было задано расход 7.6 в формуле. С другой стороны он же считает по пробегом за поездку а не от полной суточной цифры. Или ты что-то изменил?
Я думаю чтобы уже не парится, просто км в баке я подкину 6.7, меня очень устраивало, нужно только со средним расходом сделать порядок, и фиг с ним.
изменил . Теперь значения пробега и количества литров от прошлого измерения сохраняются в еепром. А раньше каждое измерение происходило в пределах одного цикла зажигания. Теперь же, включая зажигание, мы как бы продолжаем измерение, пока не наступит разница в 50 км . между текущем пробегом и сохранённом в еепром .
Я понял. Но сброс для меня как подстраховка, в принципе если бы бортовиков выдавал более менее правдиво и стабильно а не с прыжкам то 500 то 320 и т.д, я бы не сбрасывал. Хз, стоит ли так усложнятся. Меня бы устроило 6.7 в формуле и просто упорядочить вывод среднего расхода, ты уже наверняка замучился с моим скетчем.
если измерение среднего расхода придёт в норму , будешь просто пробег до заправки от него считать и все.
250км не ползуйся сбросом суточного посмотрим как работает
Ок. Понял 250 км не сбрасывая. Не до понял другое, если прийдет средний в норму.. ( Типа допустим 6.9 пришёл в норму), будешь пробег до заправки от него считать. Что ты имеешь в виду?
в строку 630 вставить kmREFUELING=Fuel*100.00/L100SR_TFT;
строки 631-647 убрать
ок. понял
Макс дела такие.... спустя 400 км пробега наконец то вышло на примерно правдивое показание 7.6 л на 100 , в начале теста было 5.4 потом в течении времени падало и упало до 3.4 и потом начало потихоньку расти и сегодня вышло на 7.6 а вечером на 8.4, но.... все это время происходило такое, километры в баке со старта показывают правильно спустя пару минут падает очень низко, например, сегодня включил зажигание км в баке 415 что есть верно, спустя пару минут упало до 51 км в баке, спустя 10 или 15 км прогона стало 10 км в баке и спустя 27 км пробега показало 26 км в баке. Похоже косяк происходит из за того что я тогда сбил суточный. Как убрать эту зависимость от полного цикла суточного пробега. Я так понимаю что от привязки к целому суточному циклу средний расход от этого зависит а за ним уже и км в баке пляшут. Так как привычка сбивать при следующей полной заправке не уйдет, и будут вечно косяки может вернуть как то логику как была раньше, я все время сбивал суточный и на средний расход это никак не влияло а км в баке было в формуле подставлен мой средний расход 6.7. Вот скетч с последними под правками которые ты говорил
Макс эти строки делают зависимость от полного суточного пробега 2000?
Komandir .Помогите ещё раз. В строке 961 я поставил 4195 ,т.е стоимость 41,95 р. за литр. в строке 4073 поставил 2:1. Поставил на автомобиль свой БК. Всё нормально ,всё что нужно показывает,только стоимость поездки делит на 10. Литр потратил должен показывать 41,95, а он выдаёт Р4,19 .Где в коде изменить ,чтобы показывало правильно. Или просто в строке 961 поставить 41950?
Сергей попробуй записать 41950 или попробуй 4195*10 или 41,95*1000