SPI MONITORをATのECUの確認が終わったので追加した。
みつさんにAT用のECUのMNE101060を貸していたので回収してSPI Monitorで動くか確認した。特に問題ないので、MNE101060の機器コードが分かったので追加した。
MNE101060のコードが、”9A000102″と分かったので、コードに追加した。あと、デバックでESP32をUSBから電源を取っていて、ECUの電源をON/OFFする延長でECU側がごみデータをはいて、その後の表示おかしくなることがあるので、ごみデーターを捨てるロジックを追加で入れた。D0から始まる機器コードが知りたいなあ。
変更したスケッチは長いので閉じているので適時開いて確認してほしい。
全部のスケッチはクリックして見る
/*
* This code is created by www.misago.com
*
* All original source code in this repository is Copyright (C) 2024 HATI
*
* For more detail (instruction and wiring diagram), visit https://www.misago.com
*/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address 0x27, 20 column and 4 rows
LiquidCrystal_I2C lcd2(0x26, 20, 4); // I2C address 0x26, 20 column and 4 rows
uint8_t databuf[64];
int receive_byte;
#define ModelNum 5
const char MEMSModel[][11] = { "MNE10089 ", "MNE10078 ", "MNE101070 ", "MNE101170 ", "MNE101060 " };
const char MEMScode[][4] = { 0x98, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x14, 0x99, 0x00, 0x02, 0x03, 0x99, 0x00, 0x03, 0x03, 0x9a, 0x00, 0x01, 0x02 };
// Dataframe command(0x80)の構造体
struct command80 {
uint8_t commnad;
uint8_t framesize; //including this byte. This should be 0x1C (28 bytes) for the frame described here.
uint8_t enginespeed1; // RPM (16 bits)
uint8_t enginespeed2; // RPM (16 bits)
uint8_t coolanttemperature; //degrees C with +55 offset and 8-bit wrap
uint8_t ambienttemperature; // degrees C with +55 offset and 8-bit wrap
uint8_t intakeairtemperature; //degrees C with +55 offset and 8-bit wrap
uint8_t fueltemperature; //degrees C with +55 offset and 8-bit wrap. This is not supported on the Mini SPi, and always appears as 0xFF.
uint8_t mapsensorvalue; //kilopascals
uint8_t batteryvoltage; //0.1V per LSB (e.g. 0x7B == 12.3V)
uint8_t throttlepotvoltage; //0.02V per LSB. WOT should probably be close to 0xFA or 5.0V.
uint8_t idleswitch; //Bit 4 will be set if the throttle is closed, and it will be clear otherwise.
uint8_t Unknown1; //Probably a bitfield. Observed as 0x24 with engine off, and 0x20 with engine running. A single sample during a fifteen minute test drive showed a value of 0x30.
uint8_t parkneutralswitch; //Zero is closed, nonzero is open.
uint8_t faultcodes1; //On the Mini SPi, only two bits in this location are checked:
// Bit 0: Coolant temp sensor fault (Code 1)
// Bit 1: Inlet air temp sensor fault (Code 2)
uint8_t faultcodes2; //On the Mini SPi, only two bits in this location are checked:
// Bit 1: Fuel pump circuit fault (Code 10)
// Bit 7: Throttle pot circuit fault (Code 16)
uint8_t Unknown2;
uint8_t Unknown3;
uint8_t Unknown4;
uint8_t idleaircontrolmotorposition; //On the Mini SPi's A-series engine, 0 is closed, and 180 is wide open.
uint8_t idlespeed1; //deviation (MSB 16 bits)
uint8_t idlespeed2; //deviation (LSB 16 bits)
uint8_t Unknown5;
uint8_t ignitionadvance; //0.5 degrees per LSB with range of -24 deg (0x00) to 103.5 deg (0xFF)
uint8_t coiltime1; //0.002 milliseconds per LSB (16 bits)
uint8_t coiltime2; //0.002 milliseconds per LSB (16 bits)
uint8_t Unknown6;
uint8_t Unknown7;
uint8_t Unknown8;
};
// Dataframe command(0x7d)の構造体
struct command7d {
uint8_t commnad;
uint8_t framesize; // including this byte (0x1f)
uint8_t Unknown1;
uint8_t throttleangle;
uint8_t Unknown2;
uint8_t airfuelratio; // but often observed to never change from 0xFF
uint8_t Unknown3;
uint8_t lambdasensorvoltage; // 5mV per LSB
uint8_t lambdasensorfrequency; //
uint8_t lambdasensordutycycle; //
uint8_t lambdasensorstatus; // 0x01 for good, any other value for no good
uint8_t loopindicator; //0 for open loop and nonzero for closed loop
uint8_t longtermtrim;
uint8_t shorttermtrim; //1% per LSB
uint8_t carboncanisterpurgevalvedutycycle;
uint8_t Unknown4;
uint8_t idlebaseposition;
uint8_t Unknown5;
uint8_t Unknown6;
uint8_t Unknown7;
uint8_t Unknown8;
uint8_t idleerror;
uint8_t Unknown9;
uint8_t UnknownA;
uint8_t UnknownB;
uint8_t UnknownC;
uint8_t UnknownD;
uint8_t UnknownE;
uint8_t UnknownF;
uint8_t Unknown10;
uint8_t Unknown11;
uint8_t Unknown12;
uint8_t Unknown13;
};
//Errorの取り出し
struct bits1 {
uint8_t coolanttempsensor : 1;
uint8_t inletairtempsensor : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
uint8_t b8 : 1;
};
struct bits2 {
uint8_t b1 : 1;
uint8_t fuelpumpcircuit : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
uint8_t throttlepotcircuit : 1;
};
union body {
uint8_t frame80[29];
command80 frame;
} data;
union body2 {
uint8_t frame7d[32];
command7d frame;
} data2;
union body3 {
uint8_t faultcode1;
struct bits1 b;
} error1;
union body4 {
uint8_t faultcode2;
struct bits2 bb;
} error2;
int Readbyte_MEMS(int *result) {
int Initerror = false, count = 0;
while (!Serial2.available()) {
count = count + 1;
;
if (count > 10000) {
Initerror = true;
return (Initerror);
}
}
//Serial2に受信データがあるか
*result = Serial2.read(); //Serial2データを読み出し
return (Initerror);
}
int Readmulti_MEMS(void) {
int i, Initerror = false, count;
// String str;
count = 0;
receive_byte = 0;
do {
receive_byte = Serial2.available();
count = count + 1;
;
if (count > 10000) {
break;
}
} while (receive_byte < 80);
if (receive_byte == 0) {
Initerror = true;
return (Initerror);
}
//Serial2に受信データがあるか
for (i = 0; i < receive_byte; i++) {
databuf[i] = (uint8_t)Serial2.read();
}
databuf[receive_byte] = 0;
}
void StrtoHEX(void) {
int i;
for (i = 0; i < receive_byte; i++) {
Serial.printf("%02X", databuf[i]);
}
}
void InitMEMS(void) {
int i, j, data, count = 0, result, retry = 0;
// ゴミデータの読みだし
while (Serial2.available() != 0) {
Serial2.read();
}
//iNIT CODE 00
Serial2.write(0);
Readbyte_MEMS(&data);
// Serial.println(data);
//iNIT CODE F9
Serial2.write(0xF9);
Readbyte_MEMS(&data);
// Serial.println(data);
//iNIT CODE CA
Serial2.write(0xCA);
Readbyte_MEMS(&data);
// Serial.println(data);
//iNIT CODE 75
Serial2.write(0x75);
Readbyte_MEMS(&data);
// Serial.println(data);
//iNIT CODE D0
Serial2.write(0xd0);
delay(100);
Readmulti_MEMS();
// StrtoHEX( );
// Serial.println();
lcd.setCursor(0, 1);
// lcd.printf("TYPE=");
//コネクターを後からつけて初期が終わっていなくて、おかしくなってしまう対策。4回初期化をTry
result = false;
count = 0;
do {
for (i = 0; i < receive_byte; i++) count += databuf[i];
if (count == 0) { //retry
delay(100);
//iNIT CODE CA
Serial2.write(0xCA);
Readbyte_MEMS(&data);
//iNIT CODE 75
Serial2.write(0x75);
Readbyte_MEMS(&data);
//iNIT CODE D0
Serial2.write(0xd0);
delay(100);
Readmulti_MEMS();
for (i = 0; i < receive_byte; i++) count += databuf[i];
retry++;
}
} while ((count == 0 && retry < 4));
//Medel表示
for (j = 0; j < ModelNum; j++) {
count = 0;
for (i = 0; i < receive_byte; i++) {
if (i == 0) continue;
if (MEMScode[j][i - 1] == databuf[i]) {
count++;
if (count == (receive_byte - 1)) {
lcd.printf("%s", MEMSModel[j]);
// Serial.println("I=%d j=%d"i,j);
result = true;
break;
} else {
// Serial.printf("I=%d j=%d\n",i,j);
continue;
}
}
}
if (result == true) {
break;
}
}
//Medelが見つからなかったときは、コード表示
if (j == ModelNum) {
lcd.setCursor(0, 1);
for (i = 0; i < receive_byte; i++) lcd.printf("%02X", databuf[i]);
}
}
void setup() {
// シリアル初期化
Serial.begin(115200);
while (!Serial)
;
Serial2.begin(9600, SERIAL_8N1, 17, 16); //ピンを指定して使用する場合
while (!Serial2)
;
lcd.init(); // initialize the lcd
lcd.backlight();
lcd2.init(); // initialize the lcd
lcd2.backlight();
lcd.setCursor(0, 0); // move cursor the first row
lcd.print("www.misago.com"); // print message the fourth row
// lcd2.setCursor(0, 0); // move cursor the first row AT Second LCDS
// lcd2.print("Hello!!"); // print message the fourth row
Serial.println("Init Start");
InitMEMS();
lcd.setCursor(17, 1);
lcd.printf("Dis");
Serial.println("Init end");
delay(5000);
}
int CheckConnect(void) {
int result = false;
//iNIT CODE F4
Serial2.write(0xF4); // f4=nop
delay(50);
Readmulti_MEMS();
// StrtoHEX( str , receive_byte );
// Serial.println();
if (databuf[0] == 0xF4 && databuf[1] == 0x00) {
result = true;
}
return (result);
}
void CheckFaultcode(void) {
lcd.setCursor(8, 3);
lcd.printf("Fcode:");
//Fault codeの確認
if ((int)data.frame.faultcodes1 == 0 && (int)data.frame.faultcodes2 == 0) {
lcd.setCursor(15, 3);
lcd.printf("NoErr");
return;
}
error1.faultcode1 = data.frame.faultcodes1;
if (error1.b.coolanttempsensor != 0) {
lcd.setCursor(15, 3);
lcd.printf("C ");
}
if (error1.b.inletairtempsensor != 0) {
lcd.setCursor(16, 3);
lcd.printf("I ");
}
error2.faultcode2 = data.frame.faultcodes2;
if (error2.bb.fuelpumpcircuit != 0) {
lcd.setCursor(17, 3);
lcd.printf("F ");
}
if (error2.bb.throttlepotcircuit != 0) {
lcd.setCursor(18, 3);
lcd.printf("T ");
}
}
void loop() {
int i;
// MEMSとの接続確認
if (CheckConnect() == true) {
lcd.setCursor(17, 1);
lcd.printf("Con");
//データーフレーム(0x80)の読み出し
Serial2.write(0x80); // 80=Dataframe
delay(100);
Readmulti_MEMS();
// StrtoHEX();
// Serial.println();
// Serial.print("LOOP:eceive_byte=");
// Serial.println(receive_byte);
for (i = 0; i < receive_byte; i++) { data.frame80[i] = databuf[i]; }
//MEMSの電圧表示
lcd.setCursor(0, 2);
lcd.printf("%4.1fV", 0.1 * (float)data.frame.batteryvoltage);
//MEMSの環境温度
lcd.setCursor(6, 2);
lcd.printf("W:%3d", (int)data.frame.intakeairtemperature - 55);
lcd.setCursor(11, 2);
lcd.write(0xdf);
lcd.write('C');
//MEMSの水温
lcd.setCursor(14, 2);
lcd.printf("A:%2d", (int)data.frame.coolanttemperature - 55);
lcd.setCursor(18, 2);
lcd.write(0xdf);
lcd.write('C');
//MEMSが管理しているエンジン回転数
lcd.setCursor(0, 3);
lcd.printf("%04dRPM", (int)(data.frame.enginespeed1 * 256) + (int)data.frame.enginespeed2);
CheckFaultcode();
//Idel position
lcd2.setCursor(0, 0);
lcd2.printf("Ipos:%03d", (int)data.frame.idleaircontrolmotorposition);
//Idel speed
lcd2.setCursor(9, 0);
lcd2.printf("IdelEr%05d", (int)data.frame.idlespeed1 * 256 + (int)data.frame.idlespeed2);
//スロットル開度
lcd2.setCursor(0, 1);
lcd2.printf("Tp:%5.1f", (float)(data.frame.throttlepotvoltage) / 250 * 100); //Throttle pot voltage, 0.02V per LSB. WOT should probably be close to 0xFA or 5.0V.
lcd2.write('%');
//進角
lcd2.setCursor(10, 1);
lcd2.printf("IgAd:%05.1f", -24.0 + 0.5 * (float)data.frame.ignitionadvance); //Ignition 0.5 degrees per LSB with range of -24 deg (0x00) to 103.5 deg (0xFF)
//Coil time
// lcd2.setCursor(0, 2);
// lcd2.printf("Ctime:%4.1f",0,002*((float)data.frame.coiltime1*256+ (float)data.frame.coiltime2)); //Ignition 0.5 degrees per LSB with range of -24 deg (0x00) to 103.5 deg (0xFF)
//データーフレーム(0x7D)の読み出し
Serial2.write(0x7d); // 80=Dataframe
delay(100);
Readmulti_MEMS();
for (i = 0; i < receive_byte; i++) { data2.frame7d[i] = databuf[i]; }
//Map sensoe
lcd2.setCursor(0, 2);
lcd2.printf("Map:%03d", (int)data.frame.mapsensorvalue);
// lambda_voltage(mV)
lcd2.setCursor(8, 2);
lcd2.printf("Lamda:%4dmV", 5 * (int)data2.frame.lambdasensorvoltage); // 5mV per LSB
//Closeloop:0 for open loop and nonzero for closed loop
lcd2.setCursor(0, 3);
lcd2.printf("Cloop:");
if (data2.frame.loopindicator == 0) {
lcd2.setCursor(6, 3);
lcd2.printf("Open ");
} else {
lcd2.setCursor(6, 3);
lcd2.printf("Close");
}
//Short_trim
lcd2.setCursor(11, 3);
lcd2.printf("Trim:%3d%", data2.frame.shorttermtrim); //1% per LSB
} else {
lcd.setCursor(17, 1);
lcd.printf("Dis");
for (i = 2; i < 4; i++) {
lcd.setCursor(0, i);
lcd.printf(" ");
}
for (i = 0; i < 4; i++) {
lcd2.setCursor(0, i);
lcd2.printf(" ");
}
InitMEMS();
}
delay(500);
}
(Visited 1 times, 1 visits today)
最近のコメント