Что еще в будущем можно добавить ? сенсорную кнопку сброса среднего расхода (который хранится в еепром).
Расчет средней скорости движения. (Включаем таймер (уже есть - с момента включения зажигания это millis() ), по истечении таймера смотрим сколько проехали км (уже есть - это kmTrip), приводим к одним единицам делим путь на время, получаем среднюю скорость, расчитанную за период работы таймера) далее записываем в ячейки с еепром, среднеарифметическое и т.д. все также. Также должна быть сенсорная кнопка сброса средней скорости.
Ну и сделать дополнительный экран, где крупно будет один, 2 , 3 или 4 параметра отображаться и стрелочками можно листать параметры
средняя скорость не интересна, но идея хороша, может кому и пригодится. отдельную страницу не хочется делать, хочу на первом экране и постоянно видеть температуры и расходу, без листания. потом чуток может изменю а пока что оставлю так. затирания убрал, пока нормально, единственное в kmTrip появляется 2000 до первого километра, твое затирание не работает на нем. потом будет видно нужны затирания или нет.
есть одна фигня. вчера заправился под завязку. бак у меня 59 литров. показания дают 53 литра, думаю не ужели должен быть и второй байт, но я все точно проверл, только один байт отвечает за топливо. подключил опком и вижу что он тоже показывает 53 литра. значит датчик имеет ограничение по максимальной точек это 53 литра. бак не на 50 литров, это точно , когда заправляюсь под завязку то километров 150 стрелка в упоре в право, а потом начинает ползти в лево. 150 км это примерно 10 литр соляры, прибавим к 53 равно 63. 59 литров старндарт ну и до горла литра 3-4. уже прошел почти 80 км а стрелка в упоре в право и показывает 53 литра. так что правильные подсчеты пойдут уже после того как начнет в действительности падать ниже 53 литров.
Это просто. сделать работу всех формул по условию if (Fuel<53). Не понял про какое затирание ты говорил. Я не делал затирание, я делал чтоб не отображалось ниже 1 км и 1 л , а расход за поездку начал показывать после 5 км движения.
извени, я имел ввиду не отображение до 1 кл. строчку 257 конечно видел и поменял на 2000, у меня суточный до 2000км. сейчас добавлю if (kmTrip==2000) kmTrip = 0;
Это будет колстыль. вставь лучше последнее, так логика не будет корявой, нужно ведь аккуратно учиться программировать, а не делать костыли. В последнем случае даже 2000 км можешь за раз проехать. )) Отпишись потом как себя ведёт L100SR_TFT, теперь при вкл. зажигания сразу чтонибудь показывает?
ты прав на счет 2000ч. теперь скажи вот это ......сделать работу всех формул по условию if (Fuel<53). формул много и разных.... для Fuel и kmAge ? все я потерялся снова. слишком много инфы для меня. не соображаю вообсче.
L100SR_TFT при включении показывает последний расчет. раньше показывал 0. Не уверен, так как перепрошивался и теперь естественн 0. после длительной вечерней поезки , утром посмотрю.
подкидываю освежонный скетч с подправками
/////////////////////////////////////////////////////////////////////////////////////////
//библиотеки
///////////////////////////////////////////////////////////////////////////////////////////
#include <UTouch.h>
#include <UTFT.h>
#include <SPI.h>
#include <EEPROM.h>
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
//датчик наружней температуры
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire);
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
///////////////////////////////////////////////////////////////////////////////////
//пины экрана и тача
///////////////////////////////////////////////////////////////////////////////////
UTFT myGLCD(31,38,39,40,41);
UTouch myTouch(6,5,4,3,2);
extern uint8_t GroteskBold16x32[];
int x, y;
char currentPage;
float h;
float t;
bool Dvoet = 0;
//////////////////////////////////////////////////////////////////////////////
//все что касается OBD2
///////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
SoftwareSerial mySerial (12, 13); //RХ,TХ
#define mySerial_gauge Serial2
#define TX_gauge 16
#define TX 13
int length5 = 5;
int length6 = 6;
int length8 = 8;
int length7 = 7;
bool Init = 0;
bool InitGauge = 0;
bool dataMessageOK=0;
bool dataMessageEND = 0;
bool MessageParse = 0;
bool byte0 = 0;
bool byte1 = 0;
bool byte2 = 0;
int numberbyte = 0;
int PIDTime = 120; // задержка ожидания запроса следующего pid 2101, мс
int PresTime = 8000; // задержка между посылками запросов присутствия, мс
int waitbyte = 1; // задержка между отправкой байт в сообщении, мс
int waitbyte_gauge = 4;
int Datadelay = 50; // задержка между отрисовкой данных на LCD, мс
float L100M = 0; //расход на 100 км измеренный за поездку
float L100 = 0; //мгновенный расход литров на 100км
float LHor = 0; //мгновенный расход топлива литров в час
float L100SR = 0; //расход литров на 100км измеренный раз в интервал kmL
float L100SR_TFT = 0; // самый средний из расходов на 100км, он выводится на экран
int L100_Eeprom[11]= {10,10,10,10,10,10,10,10,10,10,10};
int n_eeprom = 0;
int MAF = 0; //26,27 байты Sensor de flujo de aire en masa
float BoostPres = 0; //28,29 байты Presión de refuerzo
int RPM = 0; //32,33 байты Velocidad del motor
int EGRmg = 0; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
float BoostPresCom = 0; //38,39 байты Comando de presión de refuerzo
int Speed = 0; //44,45 байты Velocidad del vehículo
float DesaInjQua = 0; //50,51 байты Cantidad de inyección deseada
float InjQua = 0; //52,53 байты Cantidad de la inyección
float StaDaliv = 0; //54,55 байты Inicio de la entrega
int PumpRPM = 0; //56,57 байты Velocidad de la bomba
float EGRPul = 0; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
float SolenPul = 0; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
float SolenPre = 0; //70,71 байты Relación de impulsos Presión Electroválvula de presión
float DesInj = 0; //72,73 байты Inyección deseada Inicio
float ActInj = 0; //16,17 байты Inicio de la inyección real
int TempAir = 0; //74,75 байты Temperatura del aire de admisión
int Temp = 0; //14,15 байты Temperatura del refrigerante
int TempOil = 0; //18,19 байты Temperatura del aceite del motor
int TempFuel = 0; //58,59 байты Temperatura del combustible
int Fuel = 0; //остаток топлива
int FuelIGN = 0; // количество топлвива в баке на момент включения зажигания
int Fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
int FuelTrip = 0; // количество литров топлива, израсходованное за один цикл включения зажигания
int kmAge = 0; //пробег, полученный со щитка приборов
int kmAgeIGN = 0; //пробег который был в момент включения зажигания
int kmAge_last = 0; // для формул
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
int kmTrip = 0; //пробег за один цикл включения зажигания
int kmL = 10; // интервал, через который будет происходить обновление среднего расхода на 100км
int km = kmL; // переменная для расчетов
int kmeeprom = 10; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
int kmTFT = kmeeprom; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING; // пробег до заправки на остатке топлива
int colerror = 0; //количество ошибок в правом верхнем углу третьего экрана
//float Barom = 0; // барометр
byte MessageRx[110] = {0}; // массив байтов принимаемого сообщения
byte MessageRxGauge[60] = {0}; // массив байтов принимаемого сообщения от щитка приборов
byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04}; // запрос инициализации
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1}; // запрос присутствия
byte messagePids[6] = {0x82,0x11,0xF1,0x21,0x01,0xA6}; // запрос пид 2101
byte messageREAD[8] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
byte messageERASE[7] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98}; // стирание ошибок
unsigned long prevPID = 0;
unsigned long prevPIDgauge = 0;
unsigned long prevTemperature = 0;
unsigned long prevpres = 0;
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
unsigned long prevData = 0;
unsigned long TimewaitPID, timerwaitPID = 0;
bool timerenabledPID = 0;
#define TIMEREXPIRED_PID (TimewaitPID - timerwaitPID)> 200 // здесь задержка на ожидание правильного ответа пидов, мс
unsigned long TimewaitInit, timerwaitInit = 0;
bool timerenabledInit = 0;
#define TIMEREXPIRED_Init (TimewaitInit - timerwaitInit)> 500 // здесь задержка на ожидание ответа об удачной инициализации, мс
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
mySerial.begin(10400);
Wire.begin();
rtc.begin();
dht.begin();
sensors.begin();
myGLCD.InitLCD();
myGLCD.clrScr();
myTouch.InitTouch();
myTouch.setPrecision(PREC_MEDIUM);
myGLCD.setFont(GroteskBold16x32);
currentPage = '0';
drawHomeScreen();
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить ремая и дату, залить в ардуино. в скетче закоментировать
// обратно. иначе каждый раз будет по новой выствлятся это это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2017, 7, 21, 13, 57, 0));
Temperature ();
pinMode(TX, OUTPUT);
pinMode(TX_gauge, OUTPUT);
fastinit();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP FIN
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LOOP
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
TimewaitPID = millis ();
TimewaitInit = millis ();
if (!Init) {if (!timerenabledInit){ timerwaitInit=TimewaitInit; timerenabledInit=1; initialization(); }
else if (TIMEREXPIRED_Init) timerenabledInit=0;}
else {
if (currentPage != '3'){ // если открыта страница 0,1 или 2 шлем запрос пид2101, если страница 3 - шлем запрос присутствия
if (millis() - prevPID > PIDTime) {PIDs(); prevPID = millis();}}
else if (millis() - prevpres > PresTime) {present(); prevpres = millis();}}
if (!InitGauge) {Serial.println ("Otpravil zapros adress Gauge");
digitalWrite (TX_gauge, HIGH); delay (500);
digitalWrite (TX_gauge, LOW); delay (20);
digitalWrite (TX_gauge, HIGH ); delay (15);
digitalWrite (TX_gauge, LOW); delay (5);
digitalWrite (TX_gauge, HIGH); delay (5);
mySerial_gauge.begin(9600);}
// else {if (millis() - prevPIDgauge> 1000) {PIDsGauge(); prevPIDgauge = millis();}}
receive ();
if (millis() - prevWatch > 3000) { Watch (); prevWatch = millis(); Trip ();}
if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();}
if (millis() - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 285, 0);} else {myGLCD.print(" ", 285, 0);} prevDvoet = millis(); Dvoet=!Dvoet;}
Menu();
LCDDataPrint();
}
void Trip () {
if (flagkmAgeIGN){
L100M = (float)FuelTrip/(float)kmTrip*100.00;
if (L100M<0) L100SR_TFT = 0;
if (L100M>99) L100SR_TFT = 99;
if (kmTrip>0 && kmTrip>kmTFT) {kmTFT = kmTrip + kmeeprom;
// тут считаем среднеарифметический расход из ячеек еепром
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
}
FuelTrip = FuelIGN - Fuel;
if (kmAge>kmAgeIGN) kmTrip = kmAge - kmAgeIGN;
else kmTrip = 2000 - (kmAgeIGN - kmAge); // 000 это через сколько км у тебя суточный пробег сбрасывается на ноль, поменяй если другое число
if (kmAge==kmAgeIGN) kmTrip = 0;
if (kmTrip>km) {km=kmTrip+kmL;
L100SR = (float)(Fuel_last-Fuel)/(float)(kmAge-kmAge_last) *100.00; // расход/100км - обновляется раз в 10км
kmAge_last = kmAge; Fuel_last = Fuel; // сохранение параметров с последнего измерениея
if (L100SR<0) L100SR_TFT = 0;
if (L100SR>99) L100SR_TFT = 99;
if (L100SR>0) kmREFUELING=1.00/(float)L100SR*(float)Fuel*100.00;
else kmREFUELING=1.00/(float)L100SR_TFT*(float)Fuel*100.00;
// тут записываем рандомно L100SR в одну из 11 ячеек еепром
EEPROM.write(n_eeprom, kmREFUELING*10);
n_eeprom++; if (n_eeprom>10) n_eeprom=0;
}}
}
void LCDDataPrint(){
unsigned long curData = millis();
if (millis() - prevData > Datadelay){
myGLCD.setColor(255, 255, 255);
myGLCD.printNumI(Speed, 350, 0, 3);
if (currentPage == '0') {
myGLCD.printNumF(LHor, 1, 60, 40, '.',5);
myGLCD.printNumF(L100, 1, 210, 40,'.',5 );
if (kmTrip>=5) myGLCD.printNumF(L100M, 1, 60, 75,'.',5 );
else myGLCD.print("0", 123, 75);
myGLCD.printNumF(L100SR_TFT, 1, 210, 75,'.',5 );
myGLCD.printNumI(kmREFUELING, 60, 110,5 );
myGLCD.printNumI(Fuel, 210, 110,5);
if (kmTrip>=1) myGLCD.printNumI(kmTrip, 60, 145,5);
else myGLCD.print("0", 123, 145);
if (FuelTrip>=1)myGLCD.printNumI(FuelTrip, 195, 145,5);
else myGLCD.print("0", 273, 145);
myGLCD.printNumI(PumpRPM, 210, 180,5);
myGLCD.printNumI(RPM, 210, 215,5);
myGLCD.printNumI(Temp, 415, 40, 3);
myGLCD.printNumI(TempOil, 415, 75, 3);
myGLCD.printNumI(TempFuel, 415, 110,3);
myGLCD.printNumI(sensors.getTempCByIndex(0), 415, 145 , 3);
myGLCD.printNumI(t, 415, 180, 3);
myGLCD.printNumI(TempAir, 415, 215, 3);
}
if (currentPage == '1') {
myGLCD.printNumF(StaDaliv,1, 395, 40,'.', 3);
myGLCD.printNumF(DesInj,1, 395, 75, '.', 4);
myGLCD.printNumF(ActInj,1, 395, 110,'.', 4);
myGLCD.printNumF(DesaInjQua,1, 395, 145,'.', 4);
myGLCD.printNumF(InjQua,1, 395, 180,'.', 4);
myGLCD.printNumI(MAF, 170, 215, 4);
myGLCD.printNumF(h, 1, 415, 215);
}
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
myGLCD.printNumF(BoostPres,1, 395, 40,'.', 4);
myGLCD.printNumF(BoostPresCom,1, 395, 75,'.', 4);
myGLCD.printNumI(EGRmg, 395, 110, 4);
myGLCD.printNumF(EGRPul,1, 395, 145,'.',3);
myGLCD.printNumF(SolenPul, 1, 395, 180,'.', 4);
myGLCD.printNumF(SolenPre, 0, 395, 215,'.', 3);
}
prevData = millis();
}
}
///////////////////////////////////////////////////////////////////////////
//отправка запроса пид 2101
void PIDs() {
Serial.println ("Otpravil zapros 21 01");
for (int i = 0; i < length6; i++) {
mySerial.write(messagePids[i]);
delay (waitbyte); }
}
void PIDsGauge() {
Serial.println (" Otpravil zapros 02 11 na panel");
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write(byte(0)); delay (1);
mySerial_gauge.write (0x13);
}
//отправка запроса присутствия
void present() {
Serial.println ("Otpravil zapros Present");
for (int i = 0; i < length5; i++) {
mySerial.write(messagePresent[i]);
delay (waitbyte); }
}
/////////////////////////////////////////////////////////////////////////////////////////////
//получение данных от ЭБУ, разборка входящих сообщений
/////////////////////////////////////////////////////////////////////////////////////////////
void receive () {
////////////////// работа с К-Line софт сериал 16-17 (12 контакт ОБД)
while(!InitGauge){
if (mySerial_gauge.available()) {
byte inByte = mySerial_gauge.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {mySerial_gauge.write (0x7F); delay (1);}
if (inByte==0xF0) {
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write (0x00); delay (1);
mySerial_gauge.write (0x13); delay (1); InitGauge=1; } } }
MessageParse = 0;
while (InitGauge && !MessageParse) {
if (!dataMessageOK) {
if (mySerial_gauge.read() == 0x23) {byte0=1; delay (waitbyte_gauge); }
if (mySerial_gauge.read() == 0xA1 && byte0) {byte1=1; delay (waitbyte_gauge);}
else byte0=0;
if (mySerial_gauge.read() == 0x04 && byte0 && byte1) {byte2=1; delay (waitbyte_gauge);}
else {byte0=0; byte1=0;}
if (byte0 && byte1 && byte2) {dataMessageOK = 1; byte0=0; byte1=0; byte2=0;}
numberbyte=0;}
else {
if (mySerial_gauge.available()>0) { MessageRxGauge[numberbyte] = mySerial_gauge.read(); numberbyte++; delayMicroseconds (250);}
if (numberbyte==34) {dataMessageEND = 1; dataMessageOK = 0;}
}
if (dataMessageEND) {
int crc = ( ( unsigned int )MessageRxGauge[32] << 8 ) | MessageRxGauge[33]; // парсинг контрольной суммы из 2 последних байт
int CRC =200;
for (int i = 0; i < 32; i++) CRC = CRC + MessageRxGauge[i]; // подсчет контрольной суммы байт от 0 до 31
Serial.print (" ReceiveGauge: ");
for (int i = 0; i < 34; i++) {
Serial.print(MessageRxGauge[i],HEX); Serial.print (" ");}
//при получении сообщения БЕЗ ошибок с данными от панели приборов, запишем в переменные остаток топлива и пробег
if (CRC==crc) {Serial.println (" OK!!!");
Fuel = MessageRxGauge[17]/2.00;
kmAge = (MessageRxGauge[23]+(MessageRxGauge[24]*256))/10.00;
if (!flagkmAgeIGN) { kmAgeIGN = kmAge; flagkmAgeIGN =1;}
if (!flagFuelIGN) { FuelIGN = Fuel; flagFuelIGN =1;}
}
else Serial.println (" ERROR!!!");
dataMessageEND = 0; MessageParse = 1; //mySerial_gauge.flush();
for (int i = 0; i < 34; i++) MessageRxGauge[i]=0; // очистка байтов массива
}}
////////////////// работа с К-Line софт сериал 12-13 (7 контакт ОБД)
if (mySerial.available()) {
delay(195);
int k=0;
byte inbyte=0;
while( mySerial.available() && k < 110) {
inbyte = mySerial.read();
MessageRx[k] = inbyte;
k++; }
Serial.print ("Receive: ");
for (int i = 0; i < k; i++) {
Serial.print(MessageRx[i],HEX); Serial.print (" ");}
Serial.println ("");
if (MessageRx[2]==0x83 && MessageRx[3]==0xF1 && MessageRx[4]==0x11 && MessageRx[5]==0xC1 && MessageRx[6]==0x6B && MessageRx[7]==0x8F && MessageRx[8]==0x40) {Init=1;
timerenabledInit=0;
Serial.println (" Initialization OK!!!!: ");
}
if (currentPage == '3'){
//при получении этого сообщения выдавать на третий экран "NO ERROR"
if (MessageRx[4]==0x82 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]==0x00 && MessageRx[9]==0xDC){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 165, 145);
Serial.println (" NO DTC ");
}
//при получении этого сообщения выдавать на третий экран "DTC BORRADO"
if (MessageRx[3]==0x83 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x54 && MessageRx[7]==0xFF && MessageRx[8]==0x00 && MessageRx[9]==0xD8){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 165, 145);
Serial.println (" DTC BORRADO ");
}
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]>0){
Serial.println ("DTC is found!");
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx[8]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx[11+(i*3)],6) && bitRead(MessageRx[11+(i*3)],7)){ myGLCD.setColor (0,255,0);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx[11+(i*3)],7) && bitRead(MessageRx[11+(i*3)],6)) {myGLCD.setColor (255,0,0);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx[9+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx[9+(i*3)]<=0x0F&&MessageRx[9+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}//расположение первых нулей
if (nolA)myGLCD.print(String (MessageRx[9+(i*3)],HEX), 246, (75+y)); //вторая цифра расположение
else myGLCD.print(String (MessageRx[9+(i*3)],HEX), 230, (75+y)); //расположение первых циыфр
if (MessageRx[10+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx[10+(i*3)]<=0x0F&&MessageRx[10+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;} //позиция первого ноля
if (nolB)myGLCD.print(String (MessageRx[10+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx[10+(i*3)],HEX), 262, (75+y));} //двигает воторой байт в2 и 3 соо
}
}
//прописываем формулы к данным
else if (MessageRx[3]==0x80 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x4C && MessageRx[7]==0x61 && MessageRx[8]==0x01) {
//Barom = MessageRx[39];
L100 = (float)LHor*100.0/(float)Speed;
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
MAF = ((MessageRx[29]*256)+MessageRx[30])/10;
BoostPres = ((MessageRx[31]*256)+MessageRx[32])/1000.0;
RPM = (MessageRx[35]*256)+MessageRx[36];
EGRmg = ((MessageRx[37]*256)+MessageRx[38])/10.0;
BoostPresCom = ((MessageRx[41]*256)+MessageRx[42])/1000.0;
Speed = ((MessageRx[47]*256)+MessageRx[48])/100;
DesaInjQua = ((MessageRx[53]*256)+MessageRx[54])/100.0;
InjQua = ((MessageRx[55]*256)+MessageRx[56])/100.0;
StaDaliv = ((MessageRx[57]*256)+MessageRx[58])/100.0;
PumpRPM = (MessageRx[59]*256)+MessageRx[60];
EGRPul = ((MessageRx[65]*256)+MessageRx[66])/100.0;
SolenPul = ((MessageRx[67]*256)+MessageRx[68])/100.0;
SolenPre = ((MessageRx[73]*256)+MessageRx[74])/100.0;
DesInj = ((MessageRx[75]*3)+(MessageRx[76])/100.0)+0.3;
ActInj = ((MessageRx[19]*3)+(MessageRx[20])/100.0)+0.3;
//TempAir = ((MessageRx[77]*26)-278)+MessageRx[78]/10.0;
//Temp = ((MessageRx[17]*26)-278)+MessageRx[18]/10.0;
//TempOil = ((MessageRx[21]*26)-278)+MessageRx[22]/10.0;
//TempFuel = ((MessageRx[61]*26)-278)+MessageRx[62]/10.0;
int A = 0;
if (MessageRx[77]<=0x0A) A = 277;
if (MessageRx[77]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[77]>=0x0D) A = 279;
double B = MessageRx[78]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx[77]*26)-A)+cel;
if (MessageRx[17]<=0x0A) A = 277;
if (MessageRx[17]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[17]>=0x0D) A = 279;
B = MessageRx[18]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx[17]*26)-A)+cel;
if (MessageRx[21]<=0x0A) A = 277;
if (MessageRx[21]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[21]>=0x0D) A = 279;
B = MessageRx[22]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx[21]*26)-A)+cel;
if (MessageRx[61]<=0x0A) A = 277;
if (MessageRx[61]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[61]>=0x0D) A = 279;
B = MessageRx[62]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx[61]*26)-A)+cel;
timerenabledPID=0;
}
for (int i = 0; i < 110; i++) MessageRx[i]=0; // очистка байтов массива
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//отправка запроса на диагностическое соединение
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initialization() {
Serial.println ("Otpravil zapros Init");
for (int i = 0; i < length5; i++) {
mySerial.write(messageInit[i]);
delay (5);
}
delay (55);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//стартовая инициализация
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fastinit() {
digitalWrite (TX, HIGH); // makes K-line high 3
delay(360); // wait for K-line to be clear 3
digitalWrite (TX, LOW); // makes K-line low 3
delay(25);
digitalWrite (TX, HIGH); // makes K-line high 3
delay(25); //last delay before first message
mySerial.begin(10400); // baud rate of the OBD
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//запрос чтения и стирания ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////////
void Read() {
Serial.println ("Zapros error; ");
for (int i = 0; i < length8; i++) {
mySerial.write(messageREAD[i]);
delay (waitbyte); }
}
void Erase() {
Serial.println ("Zapros erase; ");
for (int i = 0; i < length7; i++) {
mySerial.write(messageERASE[i]);
delay (waitbyte); }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка экранов и работа тачскрина
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Menu () {
if (myTouch.dataAvailable()) {
myTouch.read();
x=myTouch.getX();
y=myTouch.getY();
if (currentPage == '0') {
buttonHomeTouch();
buttonINF1Touch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '1') {
buttonHomeTouch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '2') {
buttonHomeTouch();
buttonINF1Touch();
buttonCHECKTouch(); }
if (currentPage == '3') {
buttonHomeTouch();
buttonREADTouch();
buttonERASETouch(); }}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописывает заголовки на страницах
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawHomeScreen() {
line() ;
Watch ();
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.setColor(0, 255, 0); // цвет линии зеленый
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(1,178,295,178); // линия горизонтальная
myGLCD.print("L/H", 10, 40);
myGLCD.print("L/A", 148, 40);
myGLCD.print("L/V", 10, 75);
myGLCD.print("L/M", 148, 75);
myGLCD.print("D/K", 10, 110);
myGLCD.print("D/L", 148, 110);
myGLCD.print("V/K", 10, 145);
myGLCD.print("V/L", 148, 145);
myGLCD.print("PUMP RPM", 10, 180);
myGLCD.print("Engi RPM", 10, 215);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("Oil C", 300, 75);
myGLCD.print("Fuel C", 300, 110);
myGLCD.print("Inter C", 300, 145);
myGLCD.print("Exter C", 300, 180);
myGLCD.print("IntAirC", 300, 215);
buttonHome() ;
buttonINF1() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
Watch ();
myGLCD.print("Start of Delivery *CA:", 10, 40);
myGLCD.print("Desir inject Start *CA:", 10, 75);
myGLCD.print("Actua Inject Start *CA:", 10, 110);
myGLCD.print("Desir Inject Quan mg/s:", 10, 145);
myGLCD.print("Actu Inject Quant mg/s:", 10, 180);
myGLCD.print("MAF mg/s:", 10, 215);
myGLCD.print("Humedad %:", 255, 215);
buttonHome() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_two() {
line() ;
Watch ();
myGLCD.print("Boost Press Bar:", 10, 40);
myGLCD.print("Boost Press Com Bar:", 10, 75);
myGLCD.print("EGR command mg/s:", 10, 110);
myGLCD.print("EGR Pulse Ratio %:", 10, 145);
myGLCD.print("Solenoide Pulse %:", 10, 180);
myGLCD.print("Solenoide Boost %:", 10, 215);
buttonHome() ;
buttonINF1() ;
buttonCHECK() ;
}
//----------------------------------------------------------------------------
void drawscreen_three() {
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
buttonHome();
buttonERASE();
buttonREAD();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//координаты тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawFrame(int x1, int y1, int x2, int y2) {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect (x1, y1, x2, y2);
while (myTouch.dataAvailable())
myTouch.read();
myGLCD.setColor(255, 255, 255);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка кнопок и координат тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonHome() {
myGLCD.setColor(0,0,0); // цвет кнопки -серый
myGLCD.fillRoundRect (1, 1, 80, 33); // расположение кнопки прямоугольника
myGLCD.setColor(255, 255,255); // цвет текста зеленый
myGLCD.drawRoundRect (1, 1, 65, 33); // кнопка будет рамкой
myGLCD.print("HOME", 1, 0); // центровка строки
}
void buttonHomeTouch(){
if ((x>=1) && (x<=65) &&(y>=1) && (y<=33)) {
drawFrame(1, 1, 65, 33);
currentPage = '0';
myGLCD.clrScr();
drawHomeScreen();
}}
void buttonINF1() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("INF 1", 25, 265);
}
void buttonINF1Touch() {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
currentPage = '1';
myGLCD.clrScr();
drawscreen_one();
} }
void buttonINF2() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (180, 255, 300, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (180, 255, 300, 310);
myGLCD.print("INF 2", 200, 265);
}
void buttonINF2Touch() {
if ((x>=180) && (x<=300) && (y>=255) && (y<=310)) {
drawFrame(180, 255, 300, 310);
currentPage = '2';
myGLCD.clrScr();
drawscreen_two();
}}
void buttonCHECK() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("CHECK", 375, 265);
}
void buttonCHECKTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
currentPage = '3';
myGLCD.clrScr();
drawscreen_three();
} }
void buttonERASE() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("ERASE", 25, 265);
}
void buttonERASETouch () {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
Erase(); //потом заменить на дейсвие
}}
void buttonREAD() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("READ", 375, 265);
}
void buttonREADTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
Read(); //потом заменить на дейсвие
}}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,73,479,73); // линия горизонтальная
myGLCD.drawLine(1,108,479,108); // линия горизонтальная
myGLCD.drawLine(1,143,479,143); // линия горизонтальная
myGLCD.drawLine(1,178,479,178); // линия горизонтальная
myGLCD.drawLine(1,212,479,212); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
}
/////////////////////////////////////////////////////////////////////////////////////////////
//верхняя часть экрана часы и дата отображается на всех экранах
/////////////////////////////////////////////////////////////////////////////////////////////
void Watch (){
DateTime now = rtc.now();
int m = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
myGLCD.setColor(0, 255, 0); //зеленый цвет цифры
if (date<10) {
myGLCD.print("0", 85, 0);
myGLCD.printNumI(now.day(), 100, 0); }
else if (date >=10) {
myGLCD.printNumI(now.day(), 85, 0); }
myGLCD.print("/", 115, 0);
if ( mon<10) {
myGLCD.print("0", 130, 0);
myGLCD.printNumI(now.month(), 145, 0);}
else if (mon >=10) {
myGLCD.printNumI(now.month(), 130, 0);}
myGLCD.print("/", 160, 0);
myGLCD.printNumI(now.year(), 175, 0);
if (hour<10) {
myGLCD.print("0",255, 0);
myGLCD.printNumI(now.hour(), 270, 0); }
else if(hour>=10){
myGLCD.printNumI(now.hour(), 255, 0); }
if (m<10) {
myGLCD.print("0",300, 0);
myGLCD.printNumI(now.minute(), 315, 0); }
else if (m>=10){
myGLCD.printNumI(now.minute(), 300, 0); }
myGLCD.print("Km/h", 410, 0);
}
void Temperature (){
h = dht.readHumidity();
t = dht.readTemperature();
sensors.requestTemperatures();
}
короче проверил еепром написав минискетчик, который имитирует раз в 10 км нажатием на кнопку. Всё работает супер. Когда ячейки пустые, там находится 255. Но мы, вычитывая из ячеек, делим на 10, поэтому расход показывает 25,5 при сбросе еепром или когда там пусто было изначально (наш вариант). Среднее арифметическое работает супер.
Только я ппц косякнул, вместо расхода, почему то, воткнул при записи пробег до заправки
строка 273 надо это EEPROM.write(n_eeprom, L100SR*10);
Ещё я переделаю чтобы адрес ячейки еепром выбирался не рандомно, а последовательно одна ячейка за другой. Даже после сброса питания начнет с того же места (адресс ячейки тоже решил в еепром запоминать). Это сделано чтобы все ячейки быстро заполнялись. А то при коротких поездках последние ячейки фиг когда заполнятся.
теперь скажи вот это ......сделать работу всех формул по условию if (Fuel<53). формул много и разных.... для Fuel и kmAge ? все я потерялся снова. слишком много инфы для меня. не соображаю вообсче.
Во всех формулах почти Fuel ипользуется, поэтому отменяем все формулы если 53 л и более.
viki13viki пишет:
L100SR_TFT при включении показывает последний расчет. раньше показывал 0. Не уверен, так как перепрошивался и теперь естественн 0. после длительной вечерней поезки , утром посмотрю.
перепрошивка ардуино не стирает еепром, данные по идее должны оставаться, только что проверил.
еще выведи на экран переменную L100SR посмотри как она меняется и адекватно ли. Она должна стать больше 0 через 10 км пробега, и обновляеться через каждые 10. Мониторь адекватные ли цифры показывает. Просто от неё другие формулы зависят.
проехал еще 5 км. топливо показывало 51. после остановки показало 50. во время езды так как у меня здесь повороты только в лево, правая сторона бака часто ниже а как я знаю топлива показывает меньше, то в основном катая 5 км было 46-48 литров. FuelTrip должен был от 51 начальных литров отнять например 46 и показать уже что FuelTrip- 5 литров. формула не срабатывает чтоли?
kmREFUELING так и остался на 0, хотя он же не затратил 1 лт на 5 км, а показывает он после 1 литра.
вывел на экран FuelIGN, запись происходит. нашел кое что, есть два байта отвечающих за топливо, в опкоме пишет , 17 байт топливо бак и 16 байт мгновеное топливо. я ставил 17 байт, а оказывается это байт датчика с панели, а 16 датчик бака. так вот при записи FuelIGN датчик еще не поднялся до конца а запись уже происходит 42 л а потом датчик доходит до своей позиции и показывает 46 л, но записано то уже 42, точка отсчета не та, по этому и L100SR_TFT такой большой. Поставвил 16 байт и теперь запись и уровень записывается одинаково. я ставил 17 байт так как он стабильный а 16 типа мгновенный, не стабильный. оставляю 16 байт.
Сделал пробный заезд. Теперь все стало на свои места, байт 16 даказывает что все работает, показывает пройденые км и средний расход за поездку. так же закоментировал строки для ограничения вывода после 1 и 5 км, они не нужны. Осталась одна проблема, болтание датчика в баке, из за этого бегающие расчеты и бегающие данные на экране, из за крена на повортах и подьемов и спусков . Думаю проблему можно решить так, сложный вариант, не для моих мозгов, первая запись Fuel у нас записыватся для подсчета пртраченых литров, потом делать еще одни записи в ячейки для Fuel после старта, и каждые 30 секунд или 1 минуту подсчитывать среднее и выводить на экран и кормить формулы этим средним подсчетом, тогда и L100M будет стабильным и Fuel, ну и все что пляшет от Fuel. Я так думаю...... Не знаю как будет правильнее.
Я правильно понял как поменять с 10 км обновление до 5 км. В кавычках жирным это на что нужно поменять.
125 int kmeeprom = 10(5);
123 int kmL = 10(5);
087 int L100_Eeprom[11(6)]= {10,10,10,10,10,10,10,10,10,10,10(оставить 6 ячеек)};
180 for (int i = 0; i < 11(6); i++) L100_Eeprom [i]= EEPROM.read(i);
181 for (int i = 0; i < 11(6); i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
247 for (int i = 0; i < 11(6); i++) L100_Eeprom [i]= EEPROM.read(i);
248 for (int i = 0; i < 11(6); i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
Подправленый скетч
/////////////////////////////////////////////////////////////////////////////////////////
//библиотеки
///////////////////////////////////////////////////////////////////////////////////////////
#include <UTouch.h>
#include <UTFT.h>
#include <SPI.h>
#include <EEPROM.h>
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
//датчик наружней температуры
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire);
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
///////////////////////////////////////////////////////////////////////////////////
//пины экрана и тача
///////////////////////////////////////////////////////////////////////////////////
UTFT myGLCD(31,38,39,40,41);
UTouch myTouch(6,5,4,3,2);
extern uint8_t GroteskBold16x32[];
int x, y;
char currentPage;
float h;
float t;
bool Dvoet = 0;
//////////////////////////////////////////////////////////////////////////////
//все что касается OBD2
///////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
SoftwareSerial mySerial (12, 13); //RХ,TХ
#define mySerial_gauge Serial2
#define TX_gauge 16
#define TX 13
int length5 = 5;
int length6 = 6;
int length8 = 8;
int length7 = 7;
bool Init = 0;
bool InitGauge = 0;
bool dataMessageOK=0;
bool dataMessageEND = 0;
bool MessageParse = 0;
bool byte0 = 0;
bool byte1 = 0;
bool byte2 = 0;
int numberbyte = 0;
int PIDTime = 120; // задержка ожидания запроса следующего pid 2101, мс
int PresTime = 8000; // задержка между посылками запросов присутствия, мс
int waitbyte = 1; // задержка между отправкой байт в сообщении, мс
int waitbyte_gauge = 4;
int Datadelay = 50; // задержка между отрисовкой данных на LCD, мс
float L100M = 0; //расход на 100 км измеренный за поездку
float L100 = 0; //мгновенный расход литров на 100км
float LHor = 0; //мгновенный расход топлива литров в час
float L100SR = 0; //расход литров на 100км измеренный раз в интервал kmL
float L100SR_TFT = 0; // самый средний из расходов на 100км, он выводится на экран
int L100_Eeprom[11]= {10,10,10,10,10,10,10,10,10,10,10};
int n_eeprom = 0;
int MAF = 0; //26,27 байты Sensor de flujo de aire en masa
float BoostPres = 0; //28,29 байты Presión de refuerzo
int RPM = 0; //32,33 байты Velocidad del motor
int EGRmg = 0; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
float BoostPresCom = 0; //38,39 байты Comando de presión de refuerzo
int Speed = 0; //44,45 байты Velocidad del vehículo
float DesaInjQua = 0; //50,51 байты Cantidad de inyección deseada
float InjQua = 0; //52,53 байты Cantidad de la inyección
float StaDaliv = 0; //54,55 байты Inicio de la entrega
int PumpRPM = 0; //56,57 байты Velocidad de la bomba
float EGRPul = 0; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
float SolenPul = 0; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
float SolenPre = 0; //70,71 байты Relación de impulsos Presión Electroválvula de presión
float DesInj = 0; //72,73 байты Inyección deseada Inicio
float ActInj = 0; //16,17 байты Inicio de la inyección real
int TempAir = 0; //74,75 байты Temperatura del aire de admisión
int Temp = 0; //14,15 байты Temperatura del refrigerante
int TempOil = 0; //18,19 байты Temperatura del aceite del motor
int TempFuel = 0; //58,59 байты Temperatura del combustible
int Fuel = 0; //остаток топлива
int FuelIGN = 0; // количество топлвива в баке на момент включения зажигания
int Fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
int FuelTrip = 0; // количество литров топлива, израсходованное за один цикл включения зажигания
int kmAge = 0; //пробег, полученный со щитка приборов
int kmAgeIGN = 0; //пробег который был в момент включения зажигания
int kmAge_last = 0; // для формул
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
int kmTrip = 0; //пробег за один цикл включения зажигания
int kmL = 10; // интервал, через который будет происходить обновление среднего расхода на 100км
int km = 0; // переменная для расчетов
int kmeeprom = 10; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING; // пробег до заправки на остатке топлива
int colerror = 0; //количество ошибок в правом верхнем углу третьего экрана
//float Barom = 0; // барометр
byte MessageRx[110] = {0}; // массив байтов принимаемого сообщения
byte MessageRxGauge[60] = {0}; // массив байтов принимаемого сообщения от щитка приборов
byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04}; // запрос инициализации
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1}; // запрос присутствия
byte messagePids[6] = {0x82,0x11,0xF1,0x21,0x01,0xA6}; // запрос пид 2101
byte messageREAD[8] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
byte messageERASE[7] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98}; // стирание ошибок
unsigned long prevPID = 0;
unsigned long prevPIDgauge = 0;
unsigned long prevTemperature = 0;
unsigned long prevpres = 0;
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
unsigned long prevData = 0;
unsigned long TimewaitPID, timerwaitPID = 0;
bool timerenabledPID = 0;
#define TIMEREXPIRED_PID (TimewaitPID - timerwaitPID)> 200 // здесь задержка на ожидание правильного ответа пидов, мс
unsigned long TimewaitInit, timerwaitInit = 0;
bool timerenabledInit = 0;
#define TIMEREXPIRED_Init (TimewaitInit - timerwaitInit)> 500 // здесь задержка на ожидание ответа об удачной инициализации, мс
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
mySerial.begin(10400);
Wire.begin();
rtc.begin();
dht.begin();
sensors.begin();
myGLCD.InitLCD();
myGLCD.clrScr();
myTouch.InitTouch();
myTouch.setPrecision(PREC_MEDIUM);
myGLCD.setFont(GroteskBold16x32);
currentPage = '0';
drawHomeScreen();
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить ремая и дату, залить в ардуино. в скетче закоментировать
// обратно. иначе каждый раз будет по новой выствлятся это это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2017, 7, 21, 13, 57, 0));
Temperature ();
pinMode(TX, OUTPUT);
pinMode(TX_gauge, OUTPUT);
fastinit();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP FIN
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LOOP
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
TimewaitPID = millis ();
TimewaitInit = millis ();
if (!Init) {if (!timerenabledInit){ timerwaitInit=TimewaitInit; timerenabledInit=1; initialization(); }
else if (TIMEREXPIRED_Init) timerenabledInit=0;}
else {
if (currentPage != '3'){ // если открыта страница 0,1 или 2 шлем запрос пид2101, если страница 3 - шлем запрос присутствия
if (millis() - prevPID > PIDTime) {PIDs(); prevPID = millis();}}
else if (millis() - prevpres > PresTime) {present(); prevpres = millis();}}
if (!InitGauge) {Serial.println ("Otpravil zapros adress Gauge");
digitalWrite (TX_gauge, HIGH); delay (500);
digitalWrite (TX_gauge, LOW); delay (20);
digitalWrite (TX_gauge, HIGH ); delay (15);
digitalWrite (TX_gauge, LOW); delay (5);
digitalWrite (TX_gauge, HIGH); delay (5);
mySerial_gauge.begin(9600);}
// else {if (millis() - prevPIDgauge> 1000) {PIDsGauge(); prevPIDgauge = millis();}}
receive ();
if (millis() - prevWatch > 3000) { Watch (); prevWatch = millis(); Trip ();}
if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();}
if (millis() - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 285, 0);} else {myGLCD.print(" ", 285, 0);} prevDvoet = millis(); Dvoet=!Dvoet;}
Menu();
LCDDataPrint();
}
void Trip () {
if (flagkmAgeIGN){
L100M = ((float)FuelTrip*100.00)/(float)kmTrip;
if (L100M<0) L100M = 0;
if (L100M>99) L100M = 99;
if (kmTrip-kmTFT>kmeeprom) {kmTFT = kmTrip;
// тут считаем среднеарифметический расход из ячеек еепром
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
}
FuelTrip = FuelIGN - Fuel;
if (kmAge>kmAgeIGN) kmTrip = kmAge - kmAgeIGN;
if (kmAge<kmAgeIGN) kmTrip = 2000 - (kmAgeIGN - kmAge); // 000 это через сколько км у тебя суточный пробег сбрасывается на ноль, поменяй если другое число
if (kmAge==kmAgeIGN) kmTrip = 0;
if (kmTrip-km>kmL) {km=kmTrip;
L100SR = ((float)(Fuel_last-Fuel)*100.00)/(float)kmL; // расход/100км - обновляется раз в 10км
Fuel_last = Fuel; // сохранение параметров с последнего измерениея
if (L100SR<0) L100SR = 0;
if (L100SR>99) L100SR = 99;
if (L100SR>0) kmREFUELING=((float)Fuel*100.00)/(float)L100SR;
else kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;
// тут записываем L100SR последовательно в одну из 11 ячеек еепром
//EEPROM.write (12,n_eeprom); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
n_eeprom = EEPROM.read (12);
EEPROM.write(n_eeprom, L100SR*10);
n_eeprom++; if (n_eeprom>10) n_eeprom=0;
EEPROM.write (12,n_eeprom);
}}
}
void LCDDataPrint(){
unsigned long curData = millis();
if (millis() - prevData > Datadelay){
myGLCD.setColor(255, 255, 255);
myGLCD.printNumI(Speed, 350, 0, 3);
if (currentPage == '0') {
myGLCD.printNumF(LHor, 1, 60, 40, '.',5);
myGLCD.printNumF(L100, 1, 210, 40,'.',5 );
//if (kmTrip>=1)
myGLCD.printNumF(L100M, 1, 60, 75,'.',5 );
//else myGLCD.print("0", 123, 75);
myGLCD.printNumF(L100SR_TFT, 1, 210, 75,'.',5 );
myGLCD.printNumI(kmREFUELING, 60, 110,5 );
if (Fuel<53) myGLCD.printNumI(Fuel, 210, 110,5);
else myGLCD.print("MAX", 210, 110);
//if (kmTrip>=1)
myGLCD.printNumI(kmTrip, 60, 145,5);
//else myGLCD.print("0", 123, 145);
//if (FuelTrip>=1)
myGLCD.printNumI(FuelTrip, 210, 145,5);
//else myGLCD.print("0", 273, 145);
myGLCD.printNumI(PumpRPM, 210, 180,5);
myGLCD.printNumI(RPM, 210, 215,5);
myGLCD.printNumI(Temp, 415, 40, 3);
myGLCD.printNumI(TempOil, 415, 75, 3);
myGLCD.printNumI(TempFuel, 415, 110,3);
myGLCD.printNumI(sensors.getTempCByIndex(0), 415, 145 , 3);
myGLCD.printNumI(t, 415, 180, 3);
myGLCD.printNumI(TempAir, 415, 215, 3);
}
if (currentPage == '1') {
myGLCD.printNumF(StaDaliv,1, 395, 40,'.', 3);
myGLCD.printNumF(DesInj,1, 395, 75, '.', 4);
myGLCD.printNumF(ActInj,1, 395, 110,'.', 4);
myGLCD.printNumF(DesaInjQua,1, 395, 145,'.', 4);
myGLCD.printNumF(InjQua,1, 395, 180,'.', 4);
myGLCD.printNumI(MAF, 170, 215, 4);
myGLCD.printNumF(h, 1, 415, 215);
}
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
myGLCD.printNumF(BoostPres,1, 395, 40,'.', 4);
myGLCD.printNumF(BoostPresCom,1, 395, 75,'.', 4);
myGLCD.printNumI(EGRmg, 395, 110, 4);
myGLCD.printNumF(EGRPul,1, 395, 145,'.',3);
myGLCD.printNumF(SolenPul, 1, 395, 180,'.', 4);
myGLCD.printNumF(SolenPre, 0, 395, 215,'.', 3);
}
prevData = millis();
}
}
///////////////////////////////////////////////////////////////////////////
//отправка запроса пид 2101
void PIDs() {
Serial.println ("Otpravil zapros 21 01");
for (int i = 0; i < length6; i++) {
mySerial.write(messagePids[i]);
delay (waitbyte); }
}
void PIDsGauge() {
Serial.println (" Otpravil zapros 02 11 na panel");
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write(byte(0)); delay (1);
mySerial_gauge.write (0x13);
}
//отправка запроса присутствия
void present() {
Serial.println ("Otpravil zapros Present");
for (int i = 0; i < length5; i++) {
mySerial.write(messagePresent[i]);
delay (waitbyte); }
}
/////////////////////////////////////////////////////////////////////////////////////////////
//получение данных от ЭБУ, разборка входящих сообщений
/////////////////////////////////////////////////////////////////////////////////////////////
void receive () {
////////////////// работа с К-Line софт сериал 16-17 (12 контакт ОБД)
while(!InitGauge){
if (mySerial_gauge.available()) {
byte inByte = mySerial_gauge.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {mySerial_gauge.write (0x7F); delay (1);}
if (inByte==0xF0) {
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write (0x00); delay (1);
mySerial_gauge.write (0x13); delay (1); InitGauge=1; } } }
MessageParse = 0;
while (InitGauge && !MessageParse) {
if (!dataMessageOK) {
if (mySerial_gauge.read() == 0x23) {byte0=1; delay (waitbyte_gauge); }
if (mySerial_gauge.read() == 0xA1 && byte0) {byte1=1; delay (waitbyte_gauge);}
else byte0=0;
if (mySerial_gauge.read() == 0x04 && byte0 && byte1) {byte2=1; delay (waitbyte_gauge);}
else {byte0=0; byte1=0;}
if (byte0 && byte1 && byte2) {dataMessageOK = 1; byte0=0; byte1=0; byte2=0;}
numberbyte=0;}
else {
if (mySerial_gauge.available()>0) { MessageRxGauge[numberbyte] = mySerial_gauge.read(); numberbyte++; delayMicroseconds (250);}
if (numberbyte==34) {dataMessageEND = 1; dataMessageOK = 0;}
}
if (dataMessageEND) {
int crc = ( ( unsigned int )MessageRxGauge[32] << 8 ) | MessageRxGauge[33]; // парсинг контрольной суммы из 2 последних байт
int CRC =200;
for (int i = 0; i < 32; i++) CRC = CRC + MessageRxGauge[i]; // подсчет контрольной суммы байт от 0 до 31
Serial.print (" ReceiveGauge: ");
for (int i = 0; i < 34; i++) {
Serial.print(MessageRxGauge[i],HEX); Serial.print (" ");}
//при получении сообщения БЕЗ ошибок с данными от панели приборов, запишем в переменные остаток топлива и пробег
if (CRC==crc) {Serial.println (" OK!!!");
Fuel = MessageRxGauge[16]/2.00;
kmAge = (MessageRxGauge[23]+(MessageRxGauge[24]*256))/10.00;
if (Fuel<53){
if (!flagkmAgeIGN) { kmAgeIGN = kmAge; flagkmAgeIGN =1;}
if (!flagFuelIGN) { FuelIGN = Fuel; last-Fuel = Fuel; flagFuelIGN = 1; }}
}
else Serial.println (" ERROR!!!");
dataMessageEND = 0; MessageParse = 1; //mySerial_gauge.flush();
for (int i = 0; i < 34; i++) MessageRxGauge[i]=0; // очистка байтов массива
}}
////////////////// работа с К-Line софт сериал 12-13 (7 контакт ОБД)
if (mySerial.available()) {
delay(195);
int k=0;
byte inbyte=0;
while( mySerial.available() && k < 110) {
inbyte = mySerial.read();
MessageRx[k] = inbyte;
k++; }
Serial.print ("Receive: ");
for (int i = 0; i < k; i++) {
Serial.print(MessageRx[i],HEX); Serial.print (" ");}
Serial.println ("");
if (MessageRx[2]==0x83 && MessageRx[3]==0xF1 && MessageRx[4]==0x11 && MessageRx[5]==0xC1 && MessageRx[6]==0x6B && MessageRx[7]==0x8F && MessageRx[8]==0x40) {Init=1;
timerenabledInit=0;
Serial.println (" Initialization OK!!!!: ");
}
if (currentPage == '3'){
//при получении этого сообщения выдавать на третий экран "NO ERROR"
if (MessageRx[4]==0x82 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]==0x00 && MessageRx[9]==0xDC){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 165, 145);
Serial.println (" NO DTC ");
}
//при получении этого сообщения выдавать на третий экран "DTC BORRADO"
if (MessageRx[3]==0x83 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x54 && MessageRx[7]==0xFF && MessageRx[8]==0x00 && MessageRx[9]==0xD8){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 165, 145);
Serial.println (" DTC BORRADO ");
}
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]>0){
Serial.println ("DTC is found!");
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx[8]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx[11+(i*3)],6) && bitRead(MessageRx[11+(i*3)],7)){ myGLCD.setColor (0,255,0);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx[11+(i*3)],7) && bitRead(MessageRx[11+(i*3)],6)) {myGLCD.setColor (255,0,0);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx[9+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx[9+(i*3)]<=0x0F&&MessageRx[9+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}//расположение первых нулей
if (nolA)myGLCD.print(String (MessageRx[9+(i*3)],HEX), 246, (75+y)); //вторая цифра расположение
else myGLCD.print(String (MessageRx[9+(i*3)],HEX), 230, (75+y)); //расположение первых циыфр
if (MessageRx[10+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx[10+(i*3)]<=0x0F&&MessageRx[10+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;} //позиция первого ноля
if (nolB)myGLCD.print(String (MessageRx[10+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx[10+(i*3)],HEX), 262, (75+y));} //двигает воторой байт в2 и 3 соо
}
}
//прописываем формулы к данным
else if (MessageRx[3]==0x80 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x4C && MessageRx[7]==0x61 && MessageRx[8]==0x01) {
//Barom = MessageRx[39];
L100 = (float)LHor*100.0/(float)Speed;
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
MAF = ((MessageRx[29]*256)+MessageRx[30])/10;
BoostPres = ((MessageRx[31]*256)+MessageRx[32])/1000.0;
RPM = (MessageRx[35]*256)+MessageRx[36];
EGRmg = ((MessageRx[37]*256)+MessageRx[38])/10.0;
BoostPresCom = ((MessageRx[41]*256)+MessageRx[42])/1000.0;
Speed = ((MessageRx[47]*256)+MessageRx[48])/100;
DesaInjQua = ((MessageRx[53]*256)+MessageRx[54])/100.0;
InjQua = ((MessageRx[55]*256)+MessageRx[56])/100.0;
StaDaliv = ((MessageRx[57]*256)+MessageRx[58])/100.0;
PumpRPM = (MessageRx[59]*256)+MessageRx[60];
EGRPul = ((MessageRx[65]*256)+MessageRx[66])/100.0;
SolenPul = ((MessageRx[67]*256)+MessageRx[68])/100.0;
SolenPre = ((MessageRx[73]*256)+MessageRx[74])/100.0;
DesInj = ((MessageRx[75]*3)+(MessageRx[76])/100.0)+0.3;
ActInj = ((MessageRx[19]*3)+(MessageRx[20])/100.0)+0.3;
//TempAir = ((MessageRx[77]*26)-278)+MessageRx[78]/10.0;
//Temp = ((MessageRx[17]*26)-278)+MessageRx[18]/10.0;
//TempOil = ((MessageRx[21]*26)-278)+MessageRx[22]/10.0;
//TempFuel = ((MessageRx[61]*26)-278)+MessageRx[62]/10.0;
int A = 0;
if (MessageRx[77]<=0x0A) A = 277;
if (MessageRx[77]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[77]>=0x0D) A = 279;
double B = MessageRx[78]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx[77]*26)-A)+cel;
if (MessageRx[17]<=0x0A) A = 277;
if (MessageRx[17]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[17]>=0x0D) A = 279;
B = MessageRx[18]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx[17]*26)-A)+cel;
if (MessageRx[21]<=0x0A) A = 277;
if (MessageRx[21]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[21]>=0x0D) A = 279;
B = MessageRx[22]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx[21]*26)-A)+cel;
if (MessageRx[61]<=0x0A) A = 277;
if (MessageRx[61]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[61]>=0x0D) A = 279;
B = MessageRx[62]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx[61]*26)-A)+cel;
timerenabledPID=0;
}
for (int i = 0; i < 110; i++) MessageRx[i]=0; // очистка байтов массива
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//отправка запроса на диагностическое соединение
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initialization() {
Serial.println ("Otpravil zapros Init");
for (int i = 0; i < length5; i++) {
mySerial.write(messageInit[i]);
delay (5);
}
delay (55);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//стартовая инициализация
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fastinit() {
digitalWrite (TX, HIGH); // makes K-line high 3
delay(360); // wait for K-line to be clear 3
digitalWrite (TX, LOW); // makes K-line low 3
delay(25);
digitalWrite (TX, HIGH); // makes K-line high 3
delay(25); //last delay before first message
mySerial.begin(10400); // baud rate of the OBD
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//запрос чтения и стирания ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////////
void Read() {
Serial.println ("Zapros error; ");
for (int i = 0; i < length8; i++) {
mySerial.write(messageREAD[i]);
delay (waitbyte); }
}
void Erase() {
Serial.println ("Zapros erase; ");
for (int i = 0; i < length7; i++) {
mySerial.write(messageERASE[i]);
delay (waitbyte); }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка экранов и работа тачскрина
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Menu () {
if (myTouch.dataAvailable()) {
myTouch.read();
x=myTouch.getX();
y=myTouch.getY();
if (currentPage == '0') {
buttonHomeTouch();
buttonINF1Touch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '1') {
buttonHomeTouch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '2') {
buttonHomeTouch();
buttonINF1Touch();
buttonCHECKTouch(); }
if (currentPage == '3') {
buttonHomeTouch();
buttonREADTouch();
buttonERASETouch(); }}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописывает заголовки на страницах
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawHomeScreen() {
line() ;
Watch ();
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.setColor(0, 255, 0); // цвет линии зеленый
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(1,178,295,178); // линия горизонтальная
myGLCD.print("L/H", 10, 40);
myGLCD.print("L/A", 148, 40);
myGLCD.print("L/V", 10, 75);
myGLCD.print("L/M", 148, 75);
myGLCD.print("D/K", 10, 110);
myGLCD.print("D/L", 148, 110);
myGLCD.print("V/K", 10, 145);
myGLCD.print("V/L", 148, 145);
myGLCD.print("PUMP RPM", 10, 180);
myGLCD.print("Engi RPM", 10, 215);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("Oil C", 300, 75);
myGLCD.print("Fuel C", 300, 110);
myGLCD.print("Inter C", 300, 145);
myGLCD.print("Exter C", 300, 180);
myGLCD.print("IntAirC", 300, 215);
buttonHome() ;
buttonINF1() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
Watch ();
myGLCD.print("Start of Delivery *CA:", 10, 40);
myGLCD.print("Desir inject Start *CA:", 10, 75);
myGLCD.print("Actua Inject Start *CA:", 10, 110);
myGLCD.print("Desir Inject Quan mg/s:", 10, 145);
myGLCD.print("Actu Inject Quant mg/s:", 10, 180);
myGLCD.print("MAF mg/s:", 10, 215);
myGLCD.print("Humedad %:", 255, 215);
buttonHome() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_two() {
line() ;
Watch ();
myGLCD.print("Boost Press Bar:", 10, 40);
myGLCD.print("Boost Press Com Bar:", 10, 75);
myGLCD.print("EGR command mg/s:", 10, 110);
myGLCD.print("EGR Pulse Ratio %:", 10, 145);
myGLCD.print("Solenoide Pulse %:", 10, 180);
myGLCD.print("Solenoide Boost %:", 10, 215);
buttonHome() ;
buttonINF1() ;
buttonCHECK() ;
}
//----------------------------------------------------------------------------
void drawscreen_three() {
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
buttonHome();
buttonERASE();
buttonREAD();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//координаты тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawFrame(int x1, int y1, int x2, int y2) {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect (x1, y1, x2, y2);
while (myTouch.dataAvailable())
myTouch.read();
myGLCD.setColor(255, 255, 255);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка кнопок и координат тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonHome() {
myGLCD.setColor(0,0,0); // цвет кнопки -серый
myGLCD.fillRoundRect (1, 1, 80, 33); // расположение кнопки прямоугольника
myGLCD.setColor(255, 255,255); // цвет текста зеленый
myGLCD.drawRoundRect (1, 1, 65, 33); // кнопка будет рамкой
myGLCD.print("HOME", 1, 0); // центровка строки
}
void buttonHomeTouch(){
if ((x>=1) && (x<=65) &&(y>=1) && (y<=33)) {
drawFrame(1, 1, 65, 33);
currentPage = '0';
myGLCD.clrScr();
drawHomeScreen();
}}
void buttonINF1() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("INF 1", 25, 265);
}
void buttonINF1Touch() {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
currentPage = '1';
myGLCD.clrScr();
drawscreen_one();
} }
void buttonINF2() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (180, 255, 300, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (180, 255, 300, 310);
myGLCD.print("INF 2", 200, 265);
}
void buttonINF2Touch() {
if ((x>=180) && (x<=300) && (y>=255) && (y<=310)) {
drawFrame(180, 255, 300, 310);
currentPage = '2';
myGLCD.clrScr();
drawscreen_two();
}}
void buttonCHECK() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("CHECK", 375, 265);
}
void buttonCHECKTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
currentPage = '3';
myGLCD.clrScr();
drawscreen_three();
} }
void buttonERASE() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("ERASE", 25, 265);
}
void buttonERASETouch () {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
Erase(); //потом заменить на дейсвие
}}
void buttonREAD() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("READ", 375, 265);
}
void buttonREADTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
Read(); //потом заменить на дейсвие
}}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,73,479,73); // линия горизонтальная
myGLCD.drawLine(1,108,479,108); // линия горизонтальная
myGLCD.drawLine(1,143,479,143); // линия горизонтальная
myGLCD.drawLine(1,178,479,178); // линия горизонтальная
myGLCD.drawLine(1,212,479,212); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
}
/////////////////////////////////////////////////////////////////////////////////////////////
//верхняя часть экрана часы и дата отображается на всех экранах
/////////////////////////////////////////////////////////////////////////////////////////////
void Watch (){
DateTime now = rtc.now();
int m = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
myGLCD.setColor(0, 255, 0); //зеленый цвет цифры
if (date<10) {
myGLCD.print("0", 85, 0);
myGLCD.printNumI(now.day(), 100, 0); }
else if (date >=10) {
myGLCD.printNumI(now.day(), 85, 0); }
myGLCD.print("/", 115, 0);
if ( mon<10) {
myGLCD.print("0", 130, 0);
myGLCD.printNumI(now.month(), 145, 0);}
else if (mon >=10) {
myGLCD.printNumI(now.month(), 130, 0);}
myGLCD.print("/", 160, 0);
myGLCD.printNumI(now.year(), 175, 0);
if (hour<10) {
myGLCD.print("0",255, 0);
myGLCD.printNumI(now.hour(), 270, 0); }
else if(hour>=10){
myGLCD.printNumI(now.hour(), 255, 0); }
if (m<10) {
myGLCD.print("0",300, 0);
myGLCD.printNumI(now.minute(), 315, 0); }
else if (m>=10){
myGLCD.printNumI(now.minute(), 300, 0); }
myGLCD.print("Km/h", 410, 0);
}
void Temperature (){
h = dht.readHumidity();
t = dht.readTemperature();
sensors.requestTemperatures();
}
Отлично, а то я себе весь мозг уже сломал, что в формулах было не так, хотя много косяков выявлял, так бы их не нашел. (В последнем скетче уже все учтены, исправлены).
Чтобы сделать на 5 км надо только строки 123 и 125 поменять как ты указал и ВСЁ. Осталльные не трогай
насчет строки 272 говорю на всякий случай, что её нужно было только один загрузить и всё. Потом ты скетчи меняешь ее уже не нужно, пусть закоментирована, а то мало ли - Вдруг каждый скетч по два раза грузишь)
не заню. если бы другая то в опкоме бы показывало разные цифры на бак и на датчик. но они были одинаковы. один раз видел 54 но не более того. при следующей заправке проверю байты в мониторе на разницу. это сильно поменят дело? или не столь важно? если что то потом 53 можно будет подправить.
не заню. если бы другая то в опкоме бы показывало разные цифры на бак и на датчик. но они были одинаковы. один раз видел 54 но не более того. при следующей заправке проверю байты в мониторе на разницу. это сильно поменят дело? или не столь важно? если что то потом 53 можно будет подправить.
Сделал так. при старте идет запись в FuelIGN. Как только он записался, Fuel начинает вычисляться подругому - делается 10 замеров и считается среднеарифметическое, пэтому Fuel должен более плавно менятся.
Также добавил возможность заправки при включенном зажигании чобы бортовик не глючил,
т.е. если Fuel будет больше чем FuelIGN на 5 л (исключить колебания 5 л хватит) - то значит идёт заправка, скидываем все расчеты до момента, как будто только включено зажигание
/////////////////////////////////////////////////////////////////////////////////////////
//библиотеки
///////////////////////////////////////////////////////////////////////////////////////////
#include <UTouch.h>
#include <UTFT.h>
#include <SPI.h>
#include <EEPROM.h>
//pin 20 SCL , 21 SDA датчик реального времени
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
//датчик наружней температуры
#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire);
//датчик внутринней температуры и влаги
#include "DHT.h"
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
///////////////////////////////////////////////////////////////////////////////////
//пины экрана и тача
///////////////////////////////////////////////////////////////////////////////////
UTFT myGLCD(31,38,39,40,41);
UTouch myTouch(6,5,4,3,2);
extern uint8_t GroteskBold16x32[];
int x, y;
char currentPage;
float h;
float t;
bool Dvoet = 0;
//////////////////////////////////////////////////////////////////////////////
//все что касается OBD2
///////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
SoftwareSerial mySerial (12, 13); //RХ,TХ
#define mySerial_gauge Serial2
#define TX_gauge 16
#define TX 13
int length5 = 5;
int length6 = 6;
int length8 = 8;
int length7 = 7;
bool Init = 0;
bool InitGauge = 0;
bool dataMessageOK=0;
bool dataMessageEND = 0;
bool MessageParse = 0;
bool byte0 = 0;
bool byte1 = 0;
bool byte2 = 0;
int numberbyte = 0;
int PIDTime = 120; // задержка ожидания запроса следующего pid 2101, мс
int PresTime = 8000; // задержка между посылками запросов присутствия, мс
int waitbyte = 1; // задержка между отправкой байт в сообщении, мс
int waitbyte_gauge = 4;
int Datadelay = 50; // задержка между отрисовкой данных на LCD, мс
float L100M = 0; //расход на 100 км измеренный за поездку
float L100 = 0; //мгновенный расход литров на 100км
float LHor = 0; //мгновенный расход топлива литров в час
float L100SR = 0; //расход литров на 100км измеренный раз в интервал kmL
float L100SR_TFT = 0; // самый средний из расходов на 100км, он выводится на экран
int L100_Eeprom[11]= {10,10,10,10,10,10,10,10,10,10,10};
int FuelZamer[10]= {0}; // массив для измерения уровня (количества) топлива
int ZamerNumber = 0; // номер замера уровня (количества) топлива
int n_eeprom = 0; // текущий адрес ячейки еепром для записи расхода
int MAF = 0; //26,27 байты Sensor de flujo de aire en masa
float BoostPres = 0; //28,29 байты Presión de refuerzo
int RPM = 0; //32,33 байты Velocidad del motor
int EGRmg = 0; //34,35 байты Comando EGR (Comando de recirculación de gases de escape)
float BoostPresCom = 0; //38,39 байты Comando de presión de refuerzo
int Speed = 0; //44,45 байты Velocidad del vehículo
float DesaInjQua = 0; //50,51 байты Cantidad de inyección deseada
float InjQua = 0; //52,53 байты Cantidad de la inyección
float StaDaliv = 0; //54,55 байты Inicio de la entrega
int PumpRPM = 0; //56,57 байты Velocidad de la bomba
float EGRPul = 0; //62,63 байты Relación de impulsos EGR (recirculación de gases de escape
float SolenPul = 0; //64,65 байты Velocidad de solenoide de control de nivel de remolino Relación de impulsos
float SolenPre = 0; //70,71 байты Relación de impulsos Presión Electroválvula de presión
float DesInj = 0; //72,73 байты Inyección deseada Inicio
float ActInj = 0; //16,17 байты Inicio de la inyección real
int TempAir = 0; //74,75 байты Temperatura del aire de admisión
int Temp = 0; //14,15 байты Temperatura del refrigerante
int TempOil = 0; //18,19 байты Temperatura del aceite del motor
int TempFuel = 0; //58,59 байты Temperatura del combustible
int Fuel = 0; //остаток топлива
int FuelIGN = 0; // количество топлвива в баке на момент включения зажигания
int Fuel_last = 0; // для формул
bool flagFuelIGN = 0; // флаг записан ли остаток топлива в момент вкл. зажигания
int FuelTrip = 0; // количество литров топлива, израсходованное за один цикл включения зажигания
int kmAge = 0; //пробег, полученный со щитка приборов
int kmAgeIGN = 0; //пробег который был в момент включения зажигания
int kmAge_last = 0; // для формул
bool flagkmAgeIGN = 0; //флаг записан ли пробег в момент вкл. зажигания
int kmTrip = 0; //пробег за один цикл включения зажигания
int kmL = 10; // интервал, через который будет происходить обновление среднего расхода на 100км
int km = 0; // переменная для расчетов
int kmeeprom = 10; // интервал, через который будет происходить подсчет среднеарифмитического расхода L100SR_TFT
int kmTFT = 0; // переменная для расчетов периодического подсчета среднеарифмитического расхода топлива L100SR_TFT
int kmREFUELING; // пробег до заправки на остатке топлива
int colerror = 0; //количество ошибок в правом верхнем углу третьего экрана
//float Barom = 0; // барометр
byte MessageRx[110] = {0}; // массив байтов принимаемого сообщения
byte MessageRxGauge[60] = {0}; // массив байтов принимаемого сообщения от щитка приборов
byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04}; // запрос инициализации
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1}; // запрос присутствия
byte messagePids[6] = {0x82,0x11,0xF1,0x21,0x01,0xA6}; // запрос пид 2101
byte messageREAD[8] = {0x84,0x11,0xF1,0x18,0x00,0xFF,0x00,0x9D}; // запрос ошибок
byte messageERASE[7] = {0x83,0x11,0xF1,0x14,0xFF,0x00,0x98}; // стирание ошибок
unsigned long prevPID = 0;
unsigned long prevPIDgauge = 0;
unsigned long prevTemperature = 0;
unsigned long prevpres = 0;
unsigned long prevWatch = 0;
unsigned long prevDvoet = 0;
unsigned long prevData = 0;
unsigned long TimewaitPID, timerwaitPID = 0;
bool timerenabledPID = 0;
#define TIMEREXPIRED_PID (TimewaitPID - timerwaitPID)> 200 // здесь задержка на ожидание правильного ответа пидов, мс
unsigned long TimewaitInit, timerwaitInit = 0;
bool timerenabledInit = 0;
#define TIMEREXPIRED_Init (TimewaitInit - timerwaitInit)> 500 // здесь задержка на ожидание ответа об удачной инициализации, мс
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
mySerial.begin(10400);
Wire.begin();
rtc.begin();
dht.begin();
sensors.begin();
myGLCD.InitLCD();
myGLCD.clrScr();
myTouch.InitTouch();
myTouch.setPrecision(PREC_MEDIUM);
myGLCD.setFont(GroteskBold16x32);
currentPage = '0';
drawHomeScreen();
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
// строка ниже используется для настройки даты и времени часов
// раскоментировать, выставить ремая и дату, залить в ардуино. в скетче закоментировать
// обратно. иначе каждый раз будет по новой выствлятся это это же время и дата
// (год, месяц, день, часы, минуты, секунды)
//rtc.adjust(DateTime(2017, 7, 21, 13, 57, 0));
Temperature ();
pinMode(TX, OUTPUT);
pinMode(TX_gauge, OUTPUT);
fastinit();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP FIN
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LOOP
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
TimewaitPID = millis ();
TimewaitInit = millis ();
if (!Init) {if (!timerenabledInit){ timerwaitInit=TimewaitInit; timerenabledInit=1; initialization(); }
else if (TIMEREXPIRED_Init) timerenabledInit=0;}
else {
if (currentPage != '3'){ // если открыта страница 0,1 или 2 шлем запрос пид2101, если страница 3 - шлем запрос присутствия
if (millis() - prevPID > PIDTime) {PIDs(); prevPID = millis();}}
else if (millis() - prevpres > PresTime) {present(); prevpres = millis();}}
if (!InitGauge) {Serial.println ("Otpravil zapros adress Gauge");
digitalWrite (TX_gauge, HIGH); delay (500);
digitalWrite (TX_gauge, LOW); delay (20);
digitalWrite (TX_gauge, HIGH ); delay (15);
digitalWrite (TX_gauge, LOW); delay (5);
digitalWrite (TX_gauge, HIGH); delay (5);
mySerial_gauge.begin(9600);}
receive ();
if (millis() - prevWatch > 3000) { Watch (); prevWatch = millis(); Trip ();}
if (millis() - prevTemperature > 60000) { Temperature (); prevTemperature = millis();}
if (millis() - prevDvoet > 500) { if (!Dvoet) {myGLCD.print(":", 285, 0);} else {myGLCD.print(" ", 285, 0);} prevDvoet = millis(); Dvoet=!Dvoet;}
Menu();
LCDDataPrint();
}
void Trip () {
if (flagkmAgeIGN){
if (Fuel > FuelIGN + 5) {flagkmAgeIGN = 0; flagFuelIGN = 0; kmTFT = 0; km = 0;}
FuelTrip = FuelIGN - Fuel;
if (kmAge>kmAgeIGN) kmTrip = kmAge - kmAgeIGN;
if (kmAge<kmAgeIGN) kmTrip = 2000 - (kmAgeIGN - kmAge); // 2000 это через сколько км у тебя суточный пробег сбрасывается на ноль, поменяй если другое число
if (kmAge==kmAgeIGN) kmTrip = 0;
L100M = ((float)FuelTrip*100.00)/(float)kmTrip;
if (L100M<0) L100M = 0;
if (L100M>99) L100M = 99;
// ниже цикл считает среднеарифметический расход из еепром раз в пробег, указанный в переменной kmeeprom
if (kmTrip-kmTFT>kmeeprom) {kmTFT = kmTrip;
// тут считаем среднеарифметический расход из ячеек еепром
for (int i = 0; i < 11; i++) L100_Eeprom [i]= EEPROM.read(i);
for (int i = 0; i < 11; i++) L100SR_TFT = L100SR_TFT + L100_Eeprom [i];
L100SR_TFT = (float)L100SR_TFT/110.00;
if (L100SR_TFT<0) L100SR_TFT = 0;
if (L100SR_TFT>99) L100SR_TFT = 99;
}
// ниже цикл считает расход топлива за пробег, указанный в переменной kmL, здесь же запись в ячейки еепром
if (kmTrip-km>kmL) {km=kmTrip;
L100SR = ((float)(Fuel_last-Fuel)*100.00)/(float)kmL; // расход/100км - обновляется раз в 10км
Fuel_last = Fuel; // сохранение параметров с последнего измерениея
if (L100SR<0) L100SR = 0;
if (L100SR>99) L100SR = 99;
if (L100SR>0) kmREFUELING=((float)Fuel*100.00)/(float)L100SR;
else kmREFUELING=((float)Fuel*100.00)/(float)L100SR_TFT;
// тут записываем L100SR последовательно в одну из 11 ячеек еепром
//EEPROM.write (12,n_eeprom); // ЗДЕСЬ ВНИМАТЕЛЬНО. ЗАГРУЗИТЬ ПРОШИВКУ С ЭТОЙ СТРОКОЙ ОДИН РАЗ, ПОТОМ ЗАКОМЕНТИРОВАТЬ И ЕЩЁ РАЗ ЗАГРУЗИТЬ
n_eeprom = EEPROM.read (12); // в ячейке 12 хранится № текущей ячейки для записи расхода, чтобы где остановился при выкл питания, от туда и продолжил
EEPROM.write(n_eeprom, L100SR*10);
n_eeprom++; if (n_eeprom>10) n_eeprom=0;
EEPROM.write (12,n_eeprom);
}}}
void LCDDataPrint(){
unsigned long curData = millis();
if (millis() - prevData > Datadelay){
myGLCD.setColor(255, 255, 255);
myGLCD.printNumI(Speed, 350, 0, 3);
if (currentPage == '0') {
myGLCD.printNumF(LHor, 1, 60, 40, '.',5);
myGLCD.printNumF(L100, 1, 210, 40,'.',5 );
//if (kmTrip>=1)
myGLCD.printNumF(L100M, 1, 60, 75,'.',5 );
//else myGLCD.print("0", 123, 75);
myGLCD.printNumF(L100SR_TFT, 1, 210, 75,'.',5 );
myGLCD.printNumI(kmREFUELING, 60, 110,5 );
if (Fuel<53) myGLCD.printNumI(Fuel, 210, 110,5);
else myGLCD.print("MAX", 210, 110);
//if (kmTrip>=1)
myGLCD.printNumI(kmTrip, 60, 145,5);
//else myGLCD.print("0", 123, 145);
//if (FuelTrip>=1)
myGLCD.printNumI(FuelTrip, 210, 145,5);
//else myGLCD.print("0", 273, 145);
myGLCD.printNumI(PumpRPM, 210, 180,5);
myGLCD.printNumI(RPM, 210, 215,5);
myGLCD.printNumI(Temp, 415, 40, 3);
myGLCD.printNumI(TempOil, 415, 75, 3);
myGLCD.printNumI(TempFuel, 415, 110,3);
myGLCD.printNumI(sensors.getTempCByIndex(0), 415, 145 , 3);
myGLCD.printNumI(t, 415, 180, 3);
myGLCD.printNumI(TempAir, 415, 215, 3);
}
if (currentPage == '1') {
myGLCD.printNumF(StaDaliv,1, 395, 40,'.', 3);
myGLCD.printNumF(DesInj,1, 395, 75, '.', 4);
myGLCD.printNumF(ActInj,1, 395, 110,'.', 4);
myGLCD.printNumF(DesaInjQua,1, 395, 145,'.', 4);
myGLCD.printNumF(InjQua,1, 395, 180,'.', 4);
myGLCD.printNumI(MAF, 170, 215, 4);
myGLCD.printNumF(h, 1, 415, 215);
}
//----------------------------------------------------------
//страниц INF2
//----------------------------------------------------------
if (currentPage == '2') {
myGLCD.printNumF(BoostPres,1, 395, 40,'.', 4);
myGLCD.printNumF(BoostPresCom,1, 395, 75,'.', 4);
myGLCD.printNumI(EGRmg, 395, 110, 4);
myGLCD.printNumF(EGRPul,1, 395, 145,'.',3);
myGLCD.printNumF(SolenPul, 1, 395, 180,'.', 4);
myGLCD.printNumF(SolenPre, 0, 395, 215,'.', 3);
}
prevData = millis();
}
}
///////////////////////////////////////////////////////////////////////////
//отправка запроса пид 2101
void PIDs() {
Serial.println ("Otpravil zapros 21 01");
for (int i = 0; i < length6; i++) {
mySerial.write(messagePids[i]);
delay (waitbyte); }
}
void PIDsGauge() {
Serial.println (" Otpravil zapros 02 11 na panel");
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write(byte(0)); delay (1);
mySerial_gauge.write (0x13);
}
//отправка запроса присутствия
void present() {
Serial.println ("Otpravil zapros Present");
for (int i = 0; i < length5; i++) {
mySerial.write(messagePresent[i]);
delay (waitbyte); }
}
/////////////////////////////////////////////////////////////////////////////////////////////
//получение данных от ЭБУ, разборка входящих сообщений
/////////////////////////////////////////////////////////////////////////////////////////////
void receive () {
////////////////// работа с К-Line софт сериал 16-17 (12 контакт ОБД)
while(!InitGauge){
if (mySerial_gauge.available()) {
byte inByte = mySerial_gauge.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {mySerial_gauge.write (0x7F); delay (1);}
if (inByte==0xF0) {
mySerial_gauge.write (0x02); delay (1);
mySerial_gauge.write (0x11); delay (1);
mySerial_gauge.write (0x00); delay (1);
mySerial_gauge.write (0x13); delay (1); InitGauge=1; } } }
MessageParse = 0;
while (InitGauge && !MessageParse) {
if (!dataMessageOK) {
if (mySerial_gauge.read() == 0x23) {byte0=1; delay (waitbyte_gauge); }
if (mySerial_gauge.read() == 0xA1 && byte0) {byte1=1; delay (waitbyte_gauge);}
else byte0=0;
if (mySerial_gauge.read() == 0x04 && byte0 && byte1) {byte2=1; delay (waitbyte_gauge);}
else {byte0=0; byte1=0;}
if (byte0 && byte1 && byte2) {dataMessageOK = 1; byte0=0; byte1=0; byte2=0;}
numberbyte=0;}
else {
if (mySerial_gauge.available()>0) { MessageRxGauge[numberbyte] = mySerial_gauge.read(); numberbyte++; delayMicroseconds (250);}
if (numberbyte==34) {dataMessageEND = 1; dataMessageOK = 0;}
}
if (dataMessageEND) {
int crc = ( ( unsigned int )MessageRxGauge[32] << 8 ) | MessageRxGauge[33]; // парсинг контрольной суммы из 2 последних байт
int CRC =200;
for (int i = 0; i < 32; i++) CRC = CRC + MessageRxGauge[i]; // подсчет контрольной суммы байт от 0 до 31
Serial.print (" ReceiveGauge: ");
for (int i = 0; i < 34; i++) {
Serial.print(MessageRxGauge[i],HEX); Serial.print (" ");}
//при получении сообщения БЕЗ ошибок с данными от панели приборов, запишем в переменные остаток топлива и пробег
if (CRC==crc) {Serial.println (" OK!!!");
if (!flagFuelIGN) Fuel = MessageRxGauge[16]/2.00;
else { FuelZamer[ZamerNumber] = MessageRxGauge[16]/2.00;
ZamerNumber++; if (ZamerNumber>9) ZamerNumber = 0;
if (ZamerNumber==9) {
for (int i = 0; i < 10; i++) Fuel = Fuel + FuelZamer[i];
Fuel = (float)Fuel/10.0;}
}
kmAge = (MessageRxGauge[23]+(MessageRxGauge[24]*256))/10.00;
if (Fuel<53){
if (!flagkmAgeIGN) { kmAgeIGN = kmAge; flagkmAgeIGN =1;}
if (!flagFuelIGN) { FuelIGN = Fuel; Fuel_last = Fuel; flagFuelIGN = 1; }}
}
else Serial.println (" ERROR!!!");
dataMessageEND = 0; MessageParse = 1; //mySerial_gauge.flush();
for (int i = 0; i < 34; i++) MessageRxGauge[i]=0; // очистка байтов массива
}}
////////////////// работа с К-Line софт сериал 12-13 (7 контакт ОБД)
if (mySerial.available()) {
delay(195);
int k=0;
byte inbyte=0;
while( mySerial.available() && k < 110) {
inbyte = mySerial.read();
MessageRx[k] = inbyte;
k++; }
Serial.print ("Receive: ");
for (int i = 0; i < k; i++) {
Serial.print(MessageRx[i],HEX); Serial.print (" ");}
Serial.println ("");
if (MessageRx[2]==0x83 && MessageRx[3]==0xF1 && MessageRx[4]==0x11 && MessageRx[5]==0xC1 && MessageRx[6]==0x6B && MessageRx[7]==0x8F && MessageRx[8]==0x40) {Init=1;
timerenabledInit=0;
Serial.println (" Initialization OK!!!!: ");
}
if (currentPage == '3'){
//при получении этого сообщения выдавать на третий экран "NO ERROR"
if (MessageRx[4]==0x82 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]==0x00 && MessageRx[9]==0xDC){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("NO DTC", 165, 145);
Serial.println (" NO DTC ");
}
//при получении этого сообщения выдавать на третий экран "DTC BORRADO"
if (MessageRx[3]==0x83 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x54 && MessageRx[7]==0xFF && MessageRx[8]==0x00 && MessageRx[9]==0xD8){
myGLCD.clrScr();
drawscreen_three();
myGLCD.print("DTC BORRADO", 165, 145);
Serial.println (" DTC BORRADO ");
}
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]>0){
Serial.println ("DTC is found!");
myGLCD.clrScr();
drawscreen_three();
for (int i=0; i<MessageRx[8]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx[11+(i*3)],6) && bitRead(MessageRx[11+(i*3)],7)){ myGLCD.setColor (0,255,0);
myGLCD.print(" -Passive-", 300, (75+y));} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx[11+(i*3)],7) && bitRead(MessageRx[11+(i*3)],6)) {myGLCD.setColor (255,0,0);
myGLCD.print(" -Active-", 300, (75+y));} // если DTC активный, делаем цвет красный
myGLCD.print("ERROR ", 50, (75+y));
myGLCD.printNumI((i+1), 150, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": P", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": C", 170, (75+y));
if (!bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": B", 170, (75+y));
if (bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) myGLCD.print(": U", 170, (75+y));
if (MessageRx[9+(i*3)]==0x00) {myGLCD.print("00", 230, (75+y)); nolA = 1;}
if (MessageRx[9+(i*3)]<=0x0F&&MessageRx[9+(i*3)]!=0) {myGLCD.print("0", 230, (75+y)); nolA = 1;}//расположение первых нулей
if (nolA)myGLCD.print(String (MessageRx[9+(i*3)],HEX), 246, (75+y)); //вторая цифра расположение
else myGLCD.print(String (MessageRx[9+(i*3)],HEX), 230, (75+y)); //расположение первых циыфр
if (MessageRx[10+(i*3)]==0x00) {myGLCD.print("00", 262, (75+y)); nolB = 1;}
if (MessageRx[10+(i*3)]<=0x0F&&MessageRx[10+(i*3)]!=0) {myGLCD.print("0", 262, (75+y)); nolB = 1;} //позиция первого ноля
if (nolB)myGLCD.print(String (MessageRx[10+(i*3)]),HEX, 278, (75+y));
else myGLCD.print(String (MessageRx[10+(i*3)],HEX), 262, (75+y));} //двигает воторой байт в2 и 3 соо
}
}
//прописываем формулы к данным
else if (MessageRx[3]==0x80 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x4C && MessageRx[7]==0x61 && MessageRx[8]==0x01) {
//Barom = MessageRx[39];
L100 = (float)LHor*100.0/(float)Speed;
LHor = (float)RPM* (float)InjQua*2.00/1000.0*60.00/1000.0/0.85;
MAF = ((MessageRx[29]*256)+MessageRx[30])/10;
BoostPres = ((MessageRx[31]*256)+MessageRx[32])/1000.0;
RPM = (MessageRx[35]*256)+MessageRx[36];
EGRmg = ((MessageRx[37]*256)+MessageRx[38])/10.0;
BoostPresCom = ((MessageRx[41]*256)+MessageRx[42])/1000.0;
Speed = ((MessageRx[47]*256)+MessageRx[48])/100;
DesaInjQua = ((MessageRx[53]*256)+MessageRx[54])/100.0;
InjQua = ((MessageRx[55]*256)+MessageRx[56])/100.0;
StaDaliv = ((MessageRx[57]*256)+MessageRx[58])/100.0;
PumpRPM = (MessageRx[59]*256)+MessageRx[60];
EGRPul = ((MessageRx[65]*256)+MessageRx[66])/100.0;
SolenPul = ((MessageRx[67]*256)+MessageRx[68])/100.0;
SolenPre = ((MessageRx[73]*256)+MessageRx[74])/100.0;
DesInj = ((MessageRx[75]*3)+(MessageRx[76])/100.0)+0.3;
ActInj = ((MessageRx[19]*3)+(MessageRx[20])/100.0)+0.3;
//TempAir = ((MessageRx[77]*26)-278)+MessageRx[78]/10.0;
//Temp = ((MessageRx[17]*26)-278)+MessageRx[18]/10.0;
//TempOil = ((MessageRx[21]*26)-278)+MessageRx[22]/10.0;
//TempFuel = ((MessageRx[61]*26)-278)+MessageRx[62]/10.0;
int A = 0;
if (MessageRx[77]<=0x0A) A = 277;
if (MessageRx[77]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[77]>=0x0D) A = 279;
double B = MessageRx[78]/10.0;
double cel , drob ;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempAir = ((MessageRx[77]*26)-A)+cel;
if (MessageRx[17]<=0x0A) A = 277;
if (MessageRx[17]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[17]>=0x0D) A = 279;
B = MessageRx[18]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
Temp = ((MessageRx[17]*26)-A)+cel;
if (MessageRx[21]<=0x0A) A = 277;
if (MessageRx[21]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[21]>=0x0D) A = 279;
B = MessageRx[22]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempOil = ((MessageRx[21]*26)-A)+cel;
if (MessageRx[61]<=0x0A) A = 277;
if (MessageRx[61]==0x0B || MessageRx[77]==0x0C) A = 278;
if (MessageRx[61]>=0x0D) A = 279;
B = MessageRx[62]/10.0;
drob = modf(B, &cel);
if (drob>0.6) cel++;
TempFuel = ((MessageRx[61]*26)-A)+cel;
timerenabledPID=0;
}
for (int i = 0; i < 110; i++) MessageRx[i]=0; // очистка байтов массива
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//отправка запроса на диагностическое соединение
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initialization() {
Serial.println ("Otpravil zapros Init");
for (int i = 0; i < length5; i++) {
mySerial.write(messageInit[i]);
delay (5);
}
delay (55);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//стартовая инициализация
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fastinit() {
digitalWrite (TX, HIGH); // makes K-line high 3
delay(360); // wait for K-line to be clear 3
digitalWrite (TX, LOW); // makes K-line low 3
delay(25);
digitalWrite (TX, HIGH); // makes K-line high 3
delay(25); //last delay before first message
mySerial.begin(10400); // baud rate of the OBD
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//запрос чтения и стирания ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////////
void Read() {
Serial.println ("Zapros error; ");
for (int i = 0; i < length8; i++) {
mySerial.write(messageREAD[i]);
delay (waitbyte); }
}
void Erase() {
Serial.println ("Zapros erase; ");
for (int i = 0; i < length7; i++) {
mySerial.write(messageERASE[i]);
delay (waitbyte); }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка экранов и работа тачскрина
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Menu () {
if (myTouch.dataAvailable()) {
myTouch.read();
x=myTouch.getX();
y=myTouch.getY();
if (currentPage == '0') {
buttonHomeTouch();
buttonINF1Touch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '1') {
buttonHomeTouch();
buttonINF2Touch();
buttonCHECKTouch(); }
if (currentPage == '2') {
buttonHomeTouch();
buttonINF1Touch();
buttonCHECKTouch(); }
if (currentPage == '3') {
buttonHomeTouch();
buttonREADTouch();
buttonERASETouch(); }}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописывает заголовки на страницах
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawHomeScreen() {
line() ;
Watch ();
myGLCD.drawLine(295,35,295,248); // линия вертикальная
myGLCD.setColor(0, 255, 0); // цвет линии зеленый
myGLCD.drawLine(145,35,145,178); // линия вертикальная
myGLCD.drawLine(1,178,295,178); // линия горизонтальная
myGLCD.print("L/H", 10, 40);
myGLCD.print("L/A", 148, 40);
myGLCD.print("L/V", 10, 75);
myGLCD.print("L/M", 148, 75);
myGLCD.print("D/K", 10, 110);
myGLCD.print("D/L", 148, 110);
myGLCD.print("V/K", 10, 145);
myGLCD.print("V/L", 148, 145);
myGLCD.print("PUMP RPM", 10, 180);
myGLCD.print("Engi RPM", 10, 215);
myGLCD.print("Motor C", 300, 40);
myGLCD.print("Oil C", 300, 75);
myGLCD.print("Fuel C", 300, 110);
myGLCD.print("Inter C", 300, 145);
myGLCD.print("Exter C", 300, 180);
myGLCD.print("IntAirC", 300, 215);
buttonHome() ;
buttonINF1() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_one() {
line() ;
Watch ();
myGLCD.print("Start of Delivery *CA:", 10, 40);
myGLCD.print("Desir inject Start *CA:", 10, 75);
myGLCD.print("Actua Inject Start *CA:", 10, 110);
myGLCD.print("Desir Inject Quan mg/s:", 10, 145);
myGLCD.print("Actu Inject Quant mg/s:", 10, 180);
myGLCD.print("MAF mg/s:", 10, 215);
myGLCD.print("Humedad %:", 255, 215);
buttonHome() ;
buttonINF2() ;
buttonCHECK() ;
}
//-------------------------------------------------
void drawscreen_two() {
line() ;
Watch ();
myGLCD.print("Boost Press Bar:", 10, 40);
myGLCD.print("Boost Press Com Bar:", 10, 75);
myGLCD.print("EGR command mg/s:", 10, 110);
myGLCD.print("EGR Pulse Ratio %:", 10, 145);
myGLCD.print("Solenoide Pulse %:", 10, 180);
myGLCD.print("Solenoide Boost %:", 10, 215);
buttonHome() ;
buttonINF1() ;
buttonCHECK() ;
}
//----------------------------------------------------------------------------
void drawscreen_three() {
Watch ();
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
buttonHome();
buttonERASE();
buttonREAD();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//координаты тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void drawFrame(int x1, int y1, int x2, int y2) {
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect (x1, y1, x2, y2);
while (myTouch.dataAvailable())
myTouch.read();
myGLCD.setColor(255, 255, 255);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//прорисовка кнопок и координат тача
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonHome() {
myGLCD.setColor(0,0,0); // цвет кнопки -серый
myGLCD.fillRoundRect (1, 1, 80, 33); // расположение кнопки прямоугольника
myGLCD.setColor(255, 255,255); // цвет текста зеленый
myGLCD.drawRoundRect (1, 1, 65, 33); // кнопка будет рамкой
myGLCD.print("HOME", 1, 0); // центровка строки
}
void buttonHomeTouch(){
if ((x>=1) && (x<=65) &&(y>=1) && (y<=33)) {
drawFrame(1, 1, 65, 33);
currentPage = '0';
myGLCD.clrScr();
drawHomeScreen();
}}
void buttonINF1() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("INF 1", 25, 265);
}
void buttonINF1Touch() {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
currentPage = '1';
myGLCD.clrScr();
drawscreen_one();
} }
void buttonINF2() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (180, 255, 300, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (180, 255, 300, 310);
myGLCD.print("INF 2", 200, 265);
}
void buttonINF2Touch() {
if ((x>=180) && (x<=300) && (y>=255) && (y<=310)) {
drawFrame(180, 255, 300, 310);
currentPage = '2';
myGLCD.clrScr();
drawscreen_two();
}}
void buttonCHECK() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("CHECK", 375, 265);
}
void buttonCHECKTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
currentPage = '3';
myGLCD.clrScr();
drawscreen_three();
} }
void buttonERASE() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (10, 255, 120, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (10, 255, 120, 310);
myGLCD.print("ERASE", 25, 265);
}
void buttonERASETouch () {
if ((x>=10) && (x<=120) && (y>=255) && (y<=310)) {
drawFrame(10, 255, 120, 310);
Erase(); //потом заменить на дейсвие
}}
void buttonREAD() {
myGLCD.setColor(0,0,0);
myGLCD.fillRoundRect (350, 255, 470, 310);
myGLCD.setColor(0, 255, 0);
myGLCD.drawRoundRect (350, 255, 470, 310);
myGLCD.print("READ", 375, 265);
}
void buttonREADTouch() {
if ((x>=350) && (x<=470) && (y>=255) && (y<=310)) {
drawFrame(350, 255, 470, 310);
Read(); //потом заменить на дейсвие
}}
////////////////////////////////////////////////////////////////////////////////////////
//прорисовка линий
///////////////////////////////////////////////////////////////////////////////////////
void line() {
myGLCD.setColor(255, 0, 0); // цвет линии красный
myGLCD.drawLine(1,35,479,35); // линия горизонтальная
myGLCD.drawLine(1,73,479,73); // линия горизонтальная
myGLCD.drawLine(1,108,479,108); // линия горизонтальная
myGLCD.drawLine(1,143,479,143); // линия горизонтальная
myGLCD.drawLine(1,178,479,178); // линия горизонтальная
myGLCD.drawLine(1,212,479,212); // линия горизонтальная
myGLCD.drawLine(1,248,479,248); // линия горизонтальная
}
/////////////////////////////////////////////////////////////////////////////////////////////
//верхняя часть экрана часы и дата отображается на всех экранах
/////////////////////////////////////////////////////////////////////////////////////////////
void Watch (){
DateTime now = rtc.now();
int m = now.minute();
int hour = now.hour();
int mon = now.month();
int date = now.day();
myGLCD.setColor(0, 255, 0); //зеленый цвет цифры
if (date<10) {
myGLCD.print("0", 85, 0);
myGLCD.printNumI(now.day(), 100, 0); }
else if (date >=10) {
myGLCD.printNumI(now.day(), 85, 0); }
myGLCD.print("/", 115, 0);
if ( mon<10) {
myGLCD.print("0", 130, 0);
myGLCD.printNumI(now.month(), 145, 0);}
else if (mon >=10) {
myGLCD.printNumI(now.month(), 130, 0);}
myGLCD.print("/", 160, 0);
myGLCD.printNumI(now.year(), 175, 0);
if (hour<10) {
myGLCD.print("0",255, 0);
myGLCD.printNumI(now.hour(), 270, 0); }
else if(hour>=10){
myGLCD.printNumI(now.hour(), 255, 0); }
if (m<10) {
myGLCD.print("0",300, 0);
myGLCD.printNumI(now.minute(), 315, 0); }
else if (m>=10){
myGLCD.printNumI(now.minute(), 300, 0); }
myGLCD.print("Km/h", 410, 0);
}
void Temperature (){
h = dht.readHumidity();
t = dht.readTemperature();
sensors.requestTemperatures();
}
Первый косяк это, начал ехать и kmtrip начал давать сбои, дошёл до 3 км и сбился на 0, потом 6 и на 0, потом на 4,потом на 6, последние км доехал домой накрутил 7 км не сбившись на 0. Второй косяк это, при первом перерасчете выдало 447 км в баке, второй раз попало в расчёте на такие цифры что выдало 78 км в баке. Может все таки Fuel записывать в ячейки и выводить среднее значение на экран и кормить средним формулы? Слишком нестабильные данные бака. Беспонятия
Да более инерционные, но выводит то на что попало в момент вывода, то есть, то висит 46 то 50 то 46 то 48 то MAX, короче на что попадет. Формулы я думаю так же попадают на разные цифры, слишком в разном диапазоне,вот и лажа что выдало в баке 447км а потом 78 км.
вот чуть поменял формулы. Должно получше быть. ПС для сравнения скетчей я пользуюсь он лайн сравнением текстов http://text.num2word.ru/
скетч
Что еще в будущем можно добавить ? сенсорную кнопку сброса среднего расхода (который хранится в еепром).
Расчет средней скорости движения. (Включаем таймер (уже есть - с момента включения зажигания это millis() ), по истечении таймера смотрим сколько проехали км (уже есть - это kmTrip), приводим к одним единицам делим путь на время, получаем среднюю скорость, расчитанную за период работы таймера) далее записываем в ячейки с еепром, среднеарифметическое и т.д. все также. Также должна быть сенсорная кнопка сброса средней скорости.
Ну и сделать дополнительный экран, где крупно будет один, 2 , 3 или 4 параметра отображаться и стрелочками можно листать параметры
Это просто. сделать работу всех формул по условию if (Fuel<53). Не понял про какое затирание ты говорил. Я не делал затирание, я делал чтоб не отображалось ниже 1 км и 1 л , а расход за поездку начал показывать после 5 км движения.
прочитай что написано в строке 257 и добавь это в строку 258:
if (kmTrip==2000) kmTrip = 0;
всё равно тебе не проехать 2000 км за один цикл включения зажигания. Тяжело это))
извени, я имел ввиду не отображение до 1 кл. строчку 257 конечно видел и поменял на 2000, у меня суточный до 2000км. сейчас добавлю if (kmTrip==2000) kmTrip = 0;
я вставил if (kmTrip==2000) kmTrip = 0; и теперь стоит ноль до 1 км. или всетаки вставить это
if
(kmAge==kmAgeIGN) kmTrip = 0;?
Это будет колстыль. вставь лучше последнее, так логика не будет корявой, нужно ведь аккуратно учиться программировать, а не делать костыли. В последнем случае даже 2000 км можешь за раз проехать. )) Отпишись потом как себя ведёт L100SR_TFT, теперь при вкл. зажигания сразу чтонибудь показывает?
ты прав на счет 2000ч. теперь скажи вот это ......сделать работу всех формул по условию if (Fuel<53). формул много и разных.... для Fuel и kmAge ? все я потерялся снова. слишком много инфы для меня. не соображаю вообсче.
L100SR_TFT при включении показывает последний расчет. раньше показывал 0. Не уверен, так как перепрошивался и теперь естественн 0. после длительной вечерней поезки , утром посмотрю.
подкидываю освежонный скетч с подправками
короче проверил еепром написав минискетчик, который имитирует раз в 10 км нажатием на кнопку. Всё работает супер. Когда ячейки пустые, там находится 255. Но мы, вычитывая из ячеек, делим на 10, поэтому расход показывает 25,5 при сбросе еепром или когда там пусто было изначально (наш вариант). Среднее арифметическое работает супер.
Только я ппц косякнул, вместо расхода, почему то, воткнул при записи пробег до заправки
строка 273 надо это EEPROM.write(n_eeprom, L100SR*10);
Ещё я переделаю чтобы адрес ячейки еепром выбирался не рандомно, а последовательно одна ячейка за другой. Даже после сброса питания начнет с того же места (адресс ячейки тоже решил в еепром запоминать). Это сделано чтобы все ячейки быстро заполнялись. А то при коротких поездках последние ячейки фиг когда заполнятся.
очень жду твоего волшебства. самый освеженный с подправками скетч 1062. на щет короткой дистанции это точно
исправил из 1062, и добавил все фишечки рюшечки
Во всех формулах почти Fuel ипользуется, поэтому отменяем все формулы если 53 л и более.
перепрошивка ардуино не стирает еепром, данные по идее должны оставаться, только что проверил.
еще выведи на экран переменную L100SR посмотри как она меняется и адекватно ли. Она должна стать больше 0 через 10 км пробега, и обновляеться через каждые 10. Мониторь адекватные ли цифры показывает. Просто от неё другие формулы зависят.
L100SR_TFT при включении зажигания и заводке показывает 19.2 черз пять секунд стнановятся 0.0. Проехал пять километров 0.0.
L100SR и L100SR_TFT сейчас выведу рядом и гляну
строка 273 почитай
нашел косяк, исправил в #1065
да, теперь не исчезает. не полинился накатал 11 км. чтобы произошла запись
kmREFUELING так и остался на нуле
L100SR_TFT так и остался 19.2, когда остановился промелькнуло 19.3 где то секунду
L100M показывало 40 и 20 потом остановился показало 10. и через секунд пять стало 0.0. прокатил еще метров 500, все равно 0.0
нужно понять правильные ли данные идут в FuelTrip и kmTrip, сдается мне что что FuelTrip отрицательный иногда бывает
да бывало -1, но последние 3 прокатки небыло. kmTrip показывает пробег правильно за поездку верно. как проверить FuelTrip?
ну как, примерно расчитывай сколько могло топлива израсходоваться
формулы подправил. Короче мучить их надо ппц.
проехал еще 5 км. топливо показывало 51. после остановки показало 50. во время езды так как у меня здесь повороты только в лево, правая сторона бака часто ниже а как я знаю топлива показывает меньше, то в основном катая 5 км было 46-48 литров. FuelTrip должен был от 51 начальных литров отнять например 46 и показать уже что FuelTrip- 5 литров. формула не срабатывает чтоли?
kmREFUELING так и остался на 0, хотя он же не затратил 1 лт на 5 км, а показывает он после 1 литра.
L100SR_TFT так и остался 19.2
L100M показывало 0.0.
FuelTrip так и остался 0.
может не происходит запись FuelIGN ?
ещё поправил
еще 5 км. бак был 50 лт. потом в прокате падал с 49 до 46 из-за частого кренав право. остановка после 5 км 48.
kmREFUELING так и остался на 0,
L100SR_TFT так и остался 19.2
L100M показывало 0.0.
FuelTrip показал 10 литров. а должно было показать 2 литра, по логике
через секунд 10-15 сново включил зажигание бак показал 50
сегодня после 25 км посмотрю че покажет. тогда будем делать выводы. что работает а что нет
Вообще не понятно поведение FuelTrip и L100M остальное вроде как не должно меняться до 10км
выводи его тогда тоже на экран. Может действительно тут косяк
отчет
kmTrip 0 , kmREFUELING 0 , L100SR_TFT 19.2 , Fuel 50 выезд с работы
kmTrip 11 , kmREFUELING 260 , L100SR_TFT 19.3 , Fuel 50
kmTrip 22 , kmREFUELING 258 , L100SR_TFT 17.0 , Fuel 51
kmTrip 31 , kmREFUELING 258 , L100SR_TFT 17.0 , Fuel 51 остановка дома. L100M и FuelTrip так и не появились
утро
kmTrip 0 , kmREFUELING 0 , L100SR_TFT 16.8 , Fuel 49 выезд на работу
kmTrip 11 , kmREFUELING 284 , L100SR_TFT 14.7 , Fuel 48
kmTrip 22 , kmREFUELING 470 , L100SR_TFT 13.3 , Fuel 48
kmTrip 31 , kmREFUELING 470 , L100SR_TFT 13.3 , Fuel 46 остановка на работе. L100M и FuelTrip так и не появились
На сколько я понимаю L100SR_TFT вроде как работает , по тихоньку идет к адекватному расходу
kmREFUELING чета тоже там считает. L100M не выводит потому что, что-то происходить с FuelTrip
вывел на экран FuelIGN, запись происходит. нашел кое что, есть два байта отвечающих за топливо, в опкоме пишет , 17 байт топливо бак и 16 байт мгновеное топливо. я ставил 17 байт, а оказывается это байт датчика с панели, а 16 датчик бака. так вот при записи FuelIGN датчик еще не поднялся до конца а запись уже происходит 42 л а потом датчик доходит до своей позиции и показывает 46 л, но записано то уже 42, точка отсчета не та, по этому и L100SR_TFT такой большой. Поставвил 16 байт и теперь запись и уровень записывается одинаково. я ставил 17 байт так как он стабильный а 16 типа мгновенный, не стабильный. оставляю 16 байт.
Сделал пробный заезд. Теперь все стало на свои места, байт 16 даказывает что все работает, показывает пройденые км и средний расход за поездку. так же закоментировал строки для ограничения вывода после 1 и 5 км, они не нужны. Осталась одна проблема, болтание датчика в баке, из за этого бегающие расчеты и бегающие данные на экране, из за крена на повортах и подьемов и спусков . Думаю проблему можно решить так, сложный вариант, не для моих мозгов, первая запись Fuel у нас записыватся для подсчета пртраченых литров, потом делать еще одни записи в ячейки для Fuel после старта, и каждые 30 секунд или 1 минуту подсчитывать среднее и выводить на экран и кормить формулы этим средним подсчетом, тогда и L100M будет стабильным и Fuel, ну и все что пляшет от Fuel. Я так думаю...... Не знаю как будет правильнее.
Я правильно понял как поменять с 10 км обновление до 5 км. В кавычках жирным это на что нужно поменять.
Подправленый скетч
Остался последний штрих.
Отлично, а то я себе весь мозг уже сломал, что в формулах было не так, хотя много косяков выявлял, так бы их не нашел. (В последнем скетче уже все учтены, исправлены).
Чтобы сделать на 5 км надо только строки 123 и 125 поменять как ты указал и ВСЁ. Осталльные не трогай
блин а может оставить 17 байт, но сделать при старте записи Fuel задержку секунд 10 и проблема решена?
насчет строки 272 говорю на всякий случай, что её нужно было только один загрузить и всё. Потом ты скетчи меняешь ее уже не нужно, пусть закоментирована, а то мало ли - Вдруг каждый скетч по два раза грузишь)
да не, он неадекватно показывает для расчетов, для стрелки да пойдет , чтоб не скакала, подумаю как заинерционить цифры немного
кстати при заправке до горловины ситуация теперь другая будет на 16 байте наверное
тебе виднее как правильнее это сделать. на счет 272 сразу это понял. закоментил. и уже не пишу ее.
не заню. если бы другая то в опкоме бы показывало разные цифры на бак и на датчик. но они были одинаковы. один раз видел 54 но не более того. при следующей заправке проверю байты в мониторе на разницу. это сильно поменят дело? или не столь важно? если что то потом 53 можно будет подправить.
да к стати я менял 123 и 125, все равно выдало данные на 11 километре. но проверю еще раз.
не заню. если бы другая то в опкоме бы показывало разные цифры на бак и на датчик. но они были одинаковы. один раз видел 54 но не более того. при следующей заправке проверю байты в мониторе на разницу. это сильно поменят дело? или не столь важно? если что то потом 53 можно будет подправить.
да нет, не важно это вобщемто, так мысли вслух
понял. но все равно ради интереса потом проверю
скетч 1082 строка 440 замени её на эту:
if (!flagFuelIGN) { FuelIGN = Fuel; last-Fuel = Fuel; flagFuelIGN = 1; }}
это чтобы первый замер был правильный. А то на первом замере L100SR будет 0 .
1082 подправил
Сделал так. при старте идет запись в FuelIGN. Как только он записался, Fuel начинает вычисляться подругому - делается 10 замеров и считается среднеарифметическое, пэтому Fuel должен более плавно менятся.
Также добавил возможность заправки при включенном зажигании чобы бортовик не глючил,
т.е. если Fuel будет больше чем FuelIGN на 5 л (исключить колебания 5 л хватит) - то значит идёт заправка, скидываем все расчеты до момента, как будто только включено зажигание
Как раз еду домой и посмотрим
Первый косяк это, начал ехать и kmtrip начал давать сбои, дошёл до 3 км и сбился на 0, потом 6 и на 0, потом на 4,потом на 6, последние км доехал домой накрутил 7 км не сбившись на 0. Второй косяк это, при первом перерасчете выдало 447 км в баке, второй раз попало в расчёте на такие цифры что выдало 78 км в баке. Может все таки Fuel записывать в ячейки и выводить среднее значение на экран и кормить средним формулы? Слишком нестабильные данные бака. Беспонятия
дак вообщето так и пытался сделать.
закоментируй сначала строку 244. Это фишечка для заправки с вкл. зажиганием. Может она глючит.
как проявляется нестабильность данных бака? данные бака разве не стали более инерционными?
Да более инерционные, но выводит то на что попало в момент вывода, то есть, то висит 46 то 50 то 46 то 48 то MAX, короче на что попадет. Формулы я думаю так же попадают на разные цифры, слишком в разном диапазоне,вот и лажа что выдало в баке 447км а потом 78 км.