Trochę uporządkowałem kod, teraz funkcja updateCluster() służy tylko do wysyłania tekstu na wyświetlacz i nie zawiera niepotrzebnych i zdublowanych warunków. Dodałem też możliwość kasowania błędów (testowane na biurku i wygląda, że jest ok). Kasowanie odbywa się poprzez dwuklik "Res" podczas wyświetlania błędów, wtedy uC wysyła komendę kasowania, restartuje połączenie i sprawdza ponownie błędy. Jeżdżę już z tym od grudnia z wersją v2.6.5.1 i nie zauważyłem większych nieprawidłowości. Jutro zrobię jakiś filmik z wersją, którą zamieszczam:
A3OBD2.h
należy dodać w 33 linii:
Kod:
bool deleteFaults();
A3OBD2.cpp
należy dodać w 225 linii:
Kod:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//nie podawac zadnych parametrow, funkcja kasuje bledy w ECU silnika
//a3obd2.deleteFaults();
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool A3OBD2::deleteFaults() {
char s[64];
uint8_t fc = 0;
sprintf(s, "\x03%c\x05%c", blockCounter);
if (!KWPSendBlock(s, 4)) return false;
int size = 0;
KWPReceiveBlock(s, 64, size);
if (s[2] != '\xfc') {
disconnect();
errorData++;
return false;
}
disconnect();
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//koniec A3OBD2::deleteFaults();
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Odświeżony główny program:
Kod:
//v3.0.3
#include "A3OBD2.h"
#include "RDSFIS.h"
#include <EEPROM.h>
//*******************************wpisujemy co ma nam wyswietlac*******************************
String displayName[] = {"RPM", "I.A.TEMP", "N75", "BOOST", "SUPPLY", "COOLANT", "MAF"};//kolejne nazwy, max 8 znakow i tylko wielkie litery
byte groupNumber[] = {118, 118, 118, 118, 4, 4, 3}; //numer grupy, mozna sprawdzic np. VCDSem
byte fieldNumber[] = {1, 2, 3, 4, 2, 3, 2}; //numer okna j/w
byte maxPage = 7; //ilosc danych do wyboru (jak wyzej jest 5 wartosci to wpisujemy 5)
//********************************************************************************************
byte currPage = 0; // indeks wyswietlanej informacji na starcie (+1)
int baudrateECU = 10400; //szybkosc transmisji z ECU 10400 - a3
int refreshRateFis = 500; //co ile milisekund ma odswiezac informacje na fisie - min 500ms
long fisWriteLastRefresh = 0;
byte faultNumber = 0;
long resetLastPress = 0;
long resetRate = 500; //czas miedzy kliknieciami RESET na manetce do przelaczenia sterowania
int resetCounter = 0; //
boolean toggle = false;
boolean delete_faults = false;
//byte IfWelcome = 1; //1 wyswietla tekst powitalny, 0 nie wyswietla
String fisWelcomeLine1 = "SIEMANO!"; // 1sza linia tekstu powitalnego
String fisWelcomeLine2 = "AUDI A3"; // 2ga linia tekstu powitalnego
long eepromLastUpdate = 0;
#define pin_BtnReset 2 //pin 2, przycisk Reset
#define pin_BtnUp 3 // pin 3, przycisk Gora
#define pin_BtnDown 6 // pin 6 i 3, przycisk Dol
#define pin_ChangeFIS 17 // 17/14, stan niski - sterowanie oryginalna czescia, stan wysoki - sterowanie gorna czescia
#define pinKLineRX 0 //RX - komunikacja z LM339
#define pinKLineTX 1 //TX - komunikacja z LM339
A3OBD2 a3obd2(pinKLineRX, pinKLineTX); // RX, TX
#define FIS_WRITE_ENA 11 //FIS ENA 15/11
#define FIS_WRITE_CLK 12 //FIS CLK 14/12
#define FIS_WRITE_DATA 10 //FIS DATA 16/10
RDSFIS rdsfis(FIS_WRITE_CLK, FIS_WRITE_DATA, FIS_WRITE_ENA);
void connectECU() {
delay(1000); // nie jestem pewny czy to potrzebne
a3obd2.connect(ADR_Engine, baudrateECU);
}
void welcome()
{
delay(3000);
rdsfis.FIS_WRITE_line1 = fisWelcomeLine1;
rdsfis.FIS_WRITE_line2 = fisWelcomeLine2;
updateCluster();
}
void readSensors() {
a3obd2.readSensors(groupNumber[currPage - 1]); //czytaj kanal wpisany na danej pozycji tablicy
rdsfis.FIS_WRITE_line1 = displayName[currPage - 1]; //wyswietlaj nazwe
rdsfis.FIS_WRITE_line2 = a3obd2.readSensorsData[fieldNumber[currPage - 1] - 1]; //wyswietlaj wartosc
updateCluster();
}
void readFaults() {
rdsfis.FIS_WRITE_line1 = "FAULTS:";
rdsfis.FIS_WRITE_line2 = "";
a3obd2.readFaults(); //sprawdzaj bledy
if (a3obd2.faultsCount > 0) {
if (faultNumber >= a3obd2.faultsCount) {
faultNumber = 0;
}
rdsfis.FIS_WRITE_line2 += a3obd2.readFaultsData[faultNumber];
faultNumber++;
} else {
rdsfis.FIS_WRITE_line2 = "NO FAULT";
}
if (delete_faults == true) {
rdsfis.FIS_WRITE_line1 = "DELETING";
a3obd2.deleteFaults(); //kasuj bledy
delete_faults = false;
}
updateCluster();
}
void updateCluster() {
if (millis() - fisWriteLastRefresh >= refreshRateFis) {
if ( (a3obd2.errorTimeout != 0) || (a3obd2.errorData != 0) ) { //jesli sa bledy w laczeniu lub pobieraniu danych to:
rdsfis.FIS_WRITE_line1 = "TO: ";
rdsfis.FIS_WRITE_line1 += String(a3obd2.errorTimeout);
rdsfis.FIS_WRITE_line2 = "DA: ";
rdsfis.FIS_WRITE_line2 += String(a3obd2.errorData);
}
// tu mozna kombinowac z przewijaniem tekstu, lub zmiana wyswietlanyhch danych
rdsfis.FIS_WRITE_sendTEXT(rdsfis.FIS_WRITE_line1, rdsfis.FIS_WRITE_line2);
fisWriteLastRefresh = millis();
}
}
void BtnReset()
{
resetLastPress = millis();
resetCounter++;
if (resetCounter > 1) {
toggle = !toggle;
digitalWrite(pin_ChangeFIS, toggle);
resetCounter = 0;
if (currPage == 0 && toggle == false) {
delete_faults = true;
}
}
}
void BtnUpDown()
{
//Down
if (digitalRead(pin_BtnDown) == HIGH)
{
if (currPage <= 0) currPage = maxPage + 1;
currPage--;
fisWriteLastRefresh = 0;
}
else
//Up
{
currPage++;
if (currPage > maxPage) currPage = 0;
fisWriteLastRefresh = 0;
}
}
void setup() {
pinMode(pin_BtnReset, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pin_BtnReset), BtnReset, FALLING);
pinMode(pin_BtnUp, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pin_BtnUp), BtnUpDown, FALLING);
pinMode(pin_BtnDown, INPUT_PULLUP);
pinMode(pin_ChangeFIS, OUTPUT);
currPage = EEPROM.read(255);
if ((currPage < 1) || (currPage > maxPage)) {
currPage = 1;
}
welcome();
}
void loop() {
//zapis do eepromu nr aktualnego kanalu jesli sie zmienil (co ok 10s)
if (millis() - eepromLastUpdate >= 10000) {
EEPROM.update(255, currPage);
eepromLastUpdate = millis();
}
//zeruje licznik zliczajacy wcisniecia przycisku reset w zadanym czasie
if (millis() - resetLastPress > resetRate) {
resetCounter = 0;
}
if (a3obd2.currAddr != ADR_Engine) {
connectECU();
} else {
if (currPage != 0) {
readSensors(); //czytaj kanal
} else {
readFaults(); //czytaj bledy
}
}
}
Produkcji seryjnej nie przewiduję, mam kilka zapasowych płytek, jak będę miał więcej czasu to je polutuję i będą na sprzedaż. Jak ktoś czuje się na siłach to mogę takiej osobie również wysłać samą płytkę. Robię to jedynie hobbystycznie, dla tego wolałbym aby pierwszeństwo mieli ci, którzy również chcieliby się przyczynić w jakiś sposób do rozwoju projektu, np. taz, doceniam Twoją pmoc, dla tego masz pierwszeństwo, jeśli chciałbyś mieć to u siebie. Od razu zaznaczam, że nie gwarantuję działania układu w innych samochodach. Każdy podłącza go na swoją odpowiedzialność, jedynie mogę zagwarantować, że każdą płytkę będę testował w swoim aucie.
#edit
Sprawdzałem też sytuację, gdy chcę się połączyć laptopem z ECU - aby komunikacja działała trzeba odłączać linię K od uC. Wystarczy zwykły wyłącznik ukryty gdzieś koło bezpieczników.
#edit2
Zgodnie z obietnicą wrzucam filmik, jak aktualnie to wygląda. Niektóre wartości są trochę źle wyświetlane, tzn. obciążenie silnika wyrażone w % niepotrzebnie jest pokazywane w formie 00.00, już to poprawiłem, ale nie wgrywałem tego jeszcze bo to tylko kosmetyka.