mirror of
https://github.com/stevenhowes/MXDiag.git
synced 2026-05-26 15:53:42 +01:00
364 lines
7.7 KiB
Arduino
364 lines
7.7 KiB
Arduino
#include <ESP8266WiFi.h>
|
|
#include <WiFiClient.h>
|
|
#include <ESP8266WebServer.h>
|
|
|
|
|
|
#include "jquery.h"
|
|
#include "index.h"
|
|
#include "svg.h"
|
|
#include "javascript.h"
|
|
#include "manifest.h"
|
|
#include "icon.h"
|
|
|
|
#include "dtc.h"
|
|
|
|
// Current state and previous state of the pin
|
|
int oldpin = 1;
|
|
int currentpin = 1;
|
|
|
|
// timenow of current state change, and previous
|
|
unsigned long timenow;
|
|
unsigned long statestart;
|
|
|
|
unsigned int diagcount = 0;
|
|
int firstpulsedone = 0;
|
|
|
|
int serialin = 0;
|
|
|
|
// Current diagnostic stage
|
|
int diagstate = -1;
|
|
|
|
String diagstring = "";
|
|
|
|
String dtcoutput = "";
|
|
String statoutput = "Booting...";
|
|
|
|
const char *ssid = "MX5Diag";
|
|
const char *password = "password";
|
|
|
|
int waitmilis = 0;
|
|
|
|
ESP8266WebServer server(80);
|
|
|
|
void handle_jq_js() {
|
|
server.sendHeader("Content-Encoding","gzip");
|
|
server.send_P(200, "text/javascript", jquery, sizeof(jquery));
|
|
}
|
|
|
|
void handle_mx_js() {
|
|
server.sendHeader("Content-Encoding","gzip");
|
|
server.send_P(200, "text/javascript", mxjs, sizeof(mxjs));
|
|
}
|
|
|
|
void handle_manifest_json() {
|
|
server.sendHeader("Content-Encoding","gzip");
|
|
server.send_P(200, "text/json", manifestjson, sizeof(manifestjson));
|
|
}
|
|
|
|
void handle_icon_png() {
|
|
server.sendHeader("Content-Encoding","gzip");
|
|
server.send_P(200, "image/png", iconpng, sizeof(iconpng));
|
|
}
|
|
|
|
void handle_index() {
|
|
server.sendHeader("Content-Encoding","gzip");
|
|
server.send_P(200, "text/html", indexhtml, sizeof(indexhtml));
|
|
}
|
|
|
|
void handle_go_svg() {
|
|
server.sendHeader("Content-Encoding","gzip");
|
|
server.send_P(200, "image/svg+xml", gosvg, sizeof(gosvg));
|
|
}
|
|
|
|
void handle_mz_svg() {
|
|
server.sendHeader("Content-Encoding","gzip");
|
|
server.send_P(200, "image/svg+xml", mzsvg, sizeof(mzsvg));
|
|
}
|
|
|
|
|
|
void handle_dtc() {
|
|
server.send(200, "text/plain", dtcoutput);
|
|
}
|
|
|
|
void handle_stat() {
|
|
server.send(200, "text/plain", statoutput);
|
|
}
|
|
|
|
void handle_run() {
|
|
server.send(200, "text/plain", "");
|
|
begindiag();
|
|
}
|
|
|
|
String identifydtc(String dtc)
|
|
{
|
|
int found = -1;
|
|
for(unsigned int i=0; i<(sizeof(dtc_index)/sizeof(dtc_index[0]));i++)
|
|
{
|
|
if(dtc_index[i] == dtc.toInt())
|
|
{
|
|
found = i;
|
|
}
|
|
}
|
|
|
|
if(found == -1)
|
|
return "Unknown";
|
|
else
|
|
return dtc_data[found];
|
|
}
|
|
|
|
void physicalsetup()
|
|
{
|
|
pinMode(D1, INPUT); // Signal from ECU
|
|
pinMode(D3, OUTPUT); // Diagnosis enable bin
|
|
pinMode(LED_BUILTIN, OUTPUT); // Status light
|
|
|
|
// Don't turn pull-down transistor on yet
|
|
digitalWrite(D3, LOW);
|
|
|
|
// Set up serial
|
|
Serial.begin(115200);
|
|
Serial.println();
|
|
}
|
|
|
|
void wifisetup()
|
|
{
|
|
WiFi.softAP(ssid/*, password*/);
|
|
|
|
IPAddress myIP = WiFi.softAPIP();
|
|
Serial.print("AP IP address: ");
|
|
Serial.println(myIP);
|
|
|
|
// Files served - all pre-gzipped to save flash
|
|
server.on("/jq.js", handle_jq_js);
|
|
server.on("/", handle_index);
|
|
server.on("/go.svg", handle_go_svg);
|
|
server.on("/mz.svg", handle_mz_svg);
|
|
server.on("/mx.js", handle_mx_js);
|
|
|
|
// Make Android web app work nicely
|
|
server.on("/manifest.json", handle_manifest_json);
|
|
server.on("/icon.png", handle_icon_png);
|
|
|
|
// Dynamic 'files'
|
|
server.on("/dtc", handle_dtc);
|
|
server.on("/stat", handle_stat);
|
|
server.on("/run", handle_run);
|
|
|
|
server.begin();
|
|
}
|
|
|
|
void setup()
|
|
{
|
|
physicalsetup();
|
|
wifisetup();
|
|
statoutput = "MXDiag Online";
|
|
Serial.println(statoutput);
|
|
}
|
|
|
|
void begindiag()
|
|
{
|
|
statoutput = "Turn off ignition";
|
|
Serial.println(statoutput);
|
|
|
|
waitmilis = millis() + 6000;
|
|
}
|
|
|
|
void diag()
|
|
{
|
|
// Read the pin once here
|
|
currentpin = digitalRead(D1);
|
|
|
|
if (diagstate == 0) // Default state on boot, waiting for pulse from ECU
|
|
{
|
|
// Give a little flash each cycle to show we're OK
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
delay(5);
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
delay(200);
|
|
|
|
// If the pin drops
|
|
if (currentpin == 0)
|
|
{
|
|
// Record when it happens
|
|
statestart = millis();
|
|
|
|
// Move us to the next state
|
|
diagstate = 1;
|
|
|
|
// Mirror the ECU output
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
}
|
|
}
|
|
else if (diagstate == 1) // This state is during the ECU greeting pulse
|
|
{
|
|
// If the pin comes back up, the pulse is over
|
|
if (currentpin == 1)
|
|
{
|
|
// Mirror ECU ouptut
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
|
|
// Record 'now'
|
|
timenow = millis();
|
|
|
|
// Default to returning to the wait (may not be needed)
|
|
diagstate = 0;
|
|
|
|
// Calculate the length of the pulse
|
|
int pulselength = (timenow - statestart);
|
|
|
|
// If it's too short or too long
|
|
if ((pulselength < 1000) || (pulselength > 5000))
|
|
{
|
|
// Go back to wait state
|
|
diagstate = 0;
|
|
} else {
|
|
// If it's our 3000ms goldilocks pulse, move to the next stage
|
|
statoutput = "ECU Detected";
|
|
Serial.println(statoutput);
|
|
diagstate = 2;
|
|
}
|
|
}
|
|
}
|
|
else if (diagstate == 2) // Waiting for a DTC pule
|
|
{
|
|
// If pin goes low we're starting on a pulse
|
|
if (currentpin == 0)
|
|
{
|
|
// Mirror to LED
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
|
|
// Record when it happens and calculate the length of the silence beforehand
|
|
timenow = millis();
|
|
int pulselength = (timenow - statestart);
|
|
|
|
// If it's a sensible length
|
|
if (pulselength > 100)
|
|
{
|
|
// If it's gurt then probably next DTC
|
|
if (pulselength > 3500)
|
|
{
|
|
if (firstpulsedone == 1)
|
|
{
|
|
// Divider for easy debug
|
|
diagstring = diagstring + diagcount;
|
|
|
|
diagcount = 0;
|
|
} else {
|
|
firstpulsedone = 1;
|
|
Serial.println("STATUS: Begining DTC read");
|
|
}
|
|
}
|
|
if (pulselength > 7500)
|
|
{
|
|
// Divider for easy debug
|
|
Serial.println(diagstring);
|
|
dtcoutput = dtcoutput + "<h2>P" + diagstring + "</h2>" + identifydtc(diagstring) + "<br/>";
|
|
|
|
diagstring = "";
|
|
}
|
|
}
|
|
|
|
// Record when state change occured
|
|
statestart = millis();
|
|
|
|
// Move to 3 (waiting for pulse end)
|
|
diagstate = 3;
|
|
}
|
|
}
|
|
else if (diagstate == 3) // Waits for pulse end
|
|
{
|
|
if (currentpin == 1)
|
|
{
|
|
// Mirror to LED
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
|
|
// Record when it happened
|
|
timenow = millis();
|
|
|
|
// Default to waiting for next pulse
|
|
diagstate = 2;
|
|
|
|
// Calculate pulse length
|
|
int pulselength = (timenow - statestart);
|
|
|
|
// If it's too short or too long
|
|
if ((pulselength < 300) || (pulselength > 1400))
|
|
{
|
|
// Wait for another one
|
|
diagstate = 2;
|
|
} else {
|
|
// 0.4 is short, 1.2 is long so lets split the difference
|
|
if (pulselength > 800)
|
|
{
|
|
// On late Mk1 / Mk2 all codes are 4 digit so we ignore the longs
|
|
}
|
|
else
|
|
{
|
|
diagcount++;
|
|
}
|
|
|
|
// Record for silence calculation
|
|
statestart = millis();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// An error state that stops all comms and shouts lots
|
|
statoutput = "Diagnostic failure";
|
|
Serial.println(statoutput);
|
|
}
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
server.handleClient();
|
|
|
|
// Look for instructions
|
|
if (Serial.available() > 0)
|
|
{
|
|
serialin = Serial.read();
|
|
|
|
// D for DTC
|
|
if (serialin == 68)
|
|
begindiag();
|
|
|
|
// F for fan (5 seconds)
|
|
//if (serialin == 70)
|
|
// fancycle();// TODO
|
|
|
|
// P for fuel pump (5 seconds)
|
|
//if (serialin == 80)
|
|
// fuelprime();// TODO
|
|
}
|
|
|
|
int left = (waitmilis - millis());
|
|
|
|
if( left > 0)
|
|
{
|
|
left = left / 1000;
|
|
statoutput = "Turn off ignition: " + String(left);
|
|
Serial.println(statoutput);
|
|
}
|
|
else
|
|
{
|
|
if(waitmilis != 0)
|
|
{
|
|
// Turn on diag pin
|
|
digitalWrite(D3, HIGH);
|
|
|
|
statoutput = "Turn on ignition (waiting for ECU)";
|
|
Serial.println(statoutput);
|
|
|
|
// Put us in default 'ready to go' mode
|
|
diagstate = 0;
|
|
waitmilis = 0;
|
|
}
|
|
}
|
|
|
|
if(waitmilis == 0)
|
|
if(diagstate >= 0)
|
|
diag();
|
|
|
|
}
|