PDA

View Full Version : Modular DIY Buttonbox - Outputs : V1b ESP8266 and ESP32



Killg0re NL
06-10-2018, 13:15
For now the code works on a ESP8266 with an Arduino to process, special thanks to Cyclicscooby
But i am thinking to move over to the ESP32 (more memory, and in/outputs available to assign, saves one design, and easier programming)

a link to download both sketches at once:DOWNLOAD LINK (http://www.tofnet.nl/Arduino/PC2_and_ESP.7z)


For the inputs TO the game check THIS LINK (http://forum.projectcarsgame.com/showthread.php?61987-DIY-Buttonbox-V1b-15-switches-and-8-encoder-functions&highlight=buttonbox)


The code is able to:
Show

WiFi Connected (ESP8266)
ABS (Arduino)
TCS (Arduino)
ESP (Arduino)
Light (Arduino)


OUTPUT LED

ledPin = 2; // GPIO2 on ESP8266 for status WiFi connected


The Code consists out of the sketch, and two additional files

_PC2_ESP8266_V1b.ino
data_out.h
info


ESP8266 Code

File: _PC2_ESP8266_V1b.ino


/*
===============================
= Pcars_udp_rx_v5.3r =
= See info tab, for more info =
= data_out.h file needed =
= info file optional =
===============================
*/

//============================================================================
//= Libraries
//============================================================================
// ESP8266 Wifi
#include <ESP8266WiFi.h>

// Standard Wifi UDP Lib
#include <WiFiUdp.h>

// Data from Pcars - Cut down to required fields
//#include "Data_Struct_Cut.h" Now there, but needed?

// Data for Serial - Cut down to required fields
#include "data_out.h"

//============================================================================
//= Setup Definitions
//============================================================================
unsigned int localPort = 5606; // Pcars UDP Port on all platforms
char sketchName[]= "_PC2_ESP8266_V1b.ino"; // SketchName
char sketchDate[]= "9 september 2018"; // SketchDate
byte mac[6]; // the MAC address of your Wifi shield

WiFiEventHandler gotIpEventHandler, disconnectedEventHandler;

/*
// For connection status
const char* wl_status_to_string(wl_status_t status) {
switch (status) { // Corresponds with Wifi Status Code
case WL_NO_SHIELD: return "WL_NO_SHIELD"; // 255
case WL_IDLE_STATUS: return "WL_IDLE_STATUS"; // 0
case WL_NO_SSID_AVAIL: return "WL_NO_SSID_AVAIL"; // 1
case WL_SCAN_COMPLETED: return "WL_SCAN_COMPLETED"; // 2
case WL_CONNECTED: return "WL_CONNECTED"; // 3
case WL_CONNECT_FAILED: return "WL_CONNECT_FAILED"; // 4
case WL_CONNECTION_LOST: return "WL_CONNECTION_LOST"; // 5
case WL_DISCONNECTED: return "WL_DISCONNECTED"; // 6
}
}
*/
//============================================================================
//= Storage section
//============================================================================
// WiFi fields
int status = WL_IDLE_STATUS;
int tries = 0;

char ssid[] = "ssid"; // your network SSID (name)
char pass[] = "password"; // your network password (use for WPA, or use as key for WEP)

char ssid2[] = "SSID"; // your network SSID (name)
char pass2[] = "PASSWORD"; // your network password (use for WPA, or use as key for WEP)

// Incoming UDP packet fields
byte packetBuffer[1367]; // buffer to hold incoming packet

unsigned int PartInfo = 1347; // Is PartInfo packetsize - packet size match
unsigned int Telemetry = 1367; // Is Telemetry packetsize

//bool inMenu = true;
bool inGame = false;
bool practiceStart = false;
bool raceStart = false;
byte raceLoading = 81;
bool needPartInfo = false;
bool needSetup = false;
bool firstRun = true;

// Timers
uint32_t D2oldtime = millis();
uint32_t D2delay = 1000; // 3k for testing - set to 1000
uint32_t D3oldtime = millis();
uint32_t D3delay = 1000; // 3k for testing - set to or 2010?


// Wifi Status led
//boolean status = false; // status is allready in use
boolean ledState = true;
int ledPin = 2; // GPIO2 on ESP8266
int interval = 1000;
long previousMillis = 0;
long currentMillis;

//============================================================================
//= Setup objects
//============================================================================

// Create Udp object
WiFiUDP Udp;

//============================================================================
//= Setup
//============================================================================
void setup() {
pinMode(ledPin,OUTPUT);

// WiFi.mode(WIFI_STA); // Let ESP8266 Function as Client only
// WiFi.setAutoConnect (true); // Test
// WiFi.setAutoReconnect (true); // Test
//Initialize serial and wait for port to open:
Serial.begin(115200);

gotIpEventHandler = WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP& event)
{
// Serial.print("Station connected, IP: ");
// Serial.println(WiFi.localIP());
});

disconnectedEventHandler = WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected& event)
{
Serial.println("Station disconnected");
});

// Serial.printf("Connecting to %s ...\n", ssid);

delay(2000);
Serial.println();
Serial.println("************************************************************");
Serial.print("Sketch name: "); Serial.println(sketchName);
Serial.print("Sketch date: "); Serial.println(sketchDate);
Serial.println("************************************************************");

// next three lines, Leonardo only
//while (!Serial) {; // wait for serial port to connect. Needed for Leonardo only
// }
// delay(1000);

// Set OutBuffer Headers
// Set 'startOfPacket' - Byte0
C0[0] = P0[0] = P1[0] = P2[0] = D0[0] = D1[0] = D2[0] =
D3[0] = D9[0] = S1[0] = M1[0] = startOfPacket;

// Set Packet Type - Byte 1
C0[1] = packetIsConnectInfo;
P0[1] = P1[1] = P2[1] = packetIsPartInfo;
D0[1] = D1[1] = D2[1] = D3[1] = D9[1] = packetIsDash;
S1[1] = packetIsSusp;
M1[1] = packetIsMotion;

// Set Packet Number - Byte 2
P0[2] = D0[2] = C0[2] = packetNum0;
P1[2] = D1[2] = S1[2] = M1[2] = packetNum1;
P2[2] = D2[2] = packetNum2;
D3[2] = packetNum3;
D9[2] = packetNum9;

// Set 'endOfPacket' - Byte variable
C0[3] = P0[67] = P1[67] = P2[67] =
D0[7] = D1[31] = D2[25] = D3[15] = D9[14] = S1[83] = M1[123] = endOfPacket;

C0[1] = 'C';
C0[2] = C0Disconnect;
Serial.write(C0, 4);
delay(500);

// attempt to connect to Wifi network:
while ( status != WL_CONNECTED){ // atm. status doesn't get updated
//while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect

C0[2] = C0Attempt1;
Serial.write(C0, 4);
status = WiFi.begin(ssid, pass);
WifiNotConnected(); // Execute WiFi Disconnected
// wait for retry connection attempt:
delay(4000);

// 2nd network attempt
tries++;
if (tries == 10 ) {
// Serial.println("Failed to Connect to First Network, Trying Next");
break;
}
}
if (tries == 10 ) {
while ( status != WL_CONNECTED){
//while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect

C0[2] = C0Attempt2;
Serial.write(C0, 4);
status = WiFi.begin(ssid2, pass2);
WifiNotConnected(); // Execute WiFi Disconnected
// wait for retry connection attempt:
delay(4000);
}
//End 2nd network attempt

}

// WiFi Successfully connected. Send connect packet
printWifiStatus(); // serialPrint WiFi details
C0[2] = C0Connect;
Serial.write(C0, 4);

// Start UDP
// Serial.println("UDP Begin");
Udp.begin(localPort);
}


void WifiNotConnected(){
currentMillis = millis();
if (currentMillis - previousMillis > interval)
{
previousMillis = currentMillis;
ledState = !ledState;
digitalWrite(ledPin, ledState);
}
}

//============================================================================
//= Main Loop
//============================================================================
void loop() {
if ( status != WL_CONNECTED) {

// Serial.println("Connected"); // DEBUG
//Send ConnectPacket =Disconnect
C0[1] = C0Disconnect;
Serial.write(C0, 4);

}

WifiConnected();

// If data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize) {
if (packetSize == Telemetry) {
// Serial.println("***** Received Telemetry ***** ");
Udp.read(packetBuffer, 1367);
// debug
// PacketNum = packetBuffer[2];
// GameState = packetBuffer[3];
// RaceState = packetBuffer[10];
// CarFlags = packetBuffer[110];
// int carbit3 = bitRead(packetBuffer[110], 3);
// Serial.print("TelemetryPacketNum : "); Serial.println(TelemetryPacketNum);
// Serial.print("GameSessionState : "); Serial.println(GameSessionState);
// Serial.print("RaceStateFlags : "); Serial.println(RaceStateFlags);
// Serial.print("CarFlags : "); Serial.println(CarFlags);
// Serial.print("carbit3 : "); Serial.println(carbit3);
// Serial.println(" ");
// end debug

// Set gameState flags
if (packetBuffer[3] == 1) { // In Menu - NOT driving
inGame = false;
practiceStart = false;
raceStart = false;
needSetup = true;
needPartInfo = true;
firstRun = true;
}
else {
inGame = true; // We are InGame
if (firstRun) {
needSetup = true; // Added because Race mode not sending D0.?
firstRun = false;
}
if (packetBuffer[3] == 18 && bitRead(packetBuffer[110], 3) == 1) {
practiceStart = true;
}
else {
practiceStart = false;
}
if (packetBuffer[3] == 82) {
raceStart = true;
}
else {
raceStart = true; // Was Originally false by Cyclicscooby
}
}

// Now Flags are set. Decide when to send data, ONLY when driving
if (inGame) {
if (practiceStart || raceStart) {
if (needSetup) {
needPartInfo = true;
sendDashSetup(); // packet D0
needSetup = false;
}
sendDash(); // This will decide if it sends D1/2/3/9
// sendSuspension(); // sends S1
// sendMotion(); // sends M1
}
}
} // end of If Telemetry

else if (packetSize == PartInfo) { // Packet IS PartInfo
// Serial.println("***** Received PartInfo ***** === = = = = = = = = = = = = = = = = = = =");
Udp.read(packetBuffer, 1347);
if (needPartInfo) {
sendPartInfo();
needPartInfo = false;
}
} // END OF IF PACKET T or P

} // END OF IF PACKET AVAILABLE

//raceStatus(); //Debug to show status of the Flags


} // END OF MAIN LOOP

//============================================================================
//= Send DashSetup D0 packet
//============================================================================
void sendDashSetup() {
// Serial.println("************************************* Sending DashSetup D0");
// Prepare D0
D0[3] = packetBuffer[11]; // LapsInEvent
D0[4] = packetBuffer[111]; // FuelCapacity
D0[5] = packetBuffer[126]; // MaxRpm 1st
D0[6] = packetBuffer[127]; // MaxRpm 2nd

// Send D0
delay(1);
Serial.write(D0, 8);
}

//============================================================================
//= Send a Dash 1/2/3/9 packet -
//============================================================================
void sendDash() {
// Serial.println("************************************* Sending Dash D1");
// Prepare D1 Dash packet
D1[3] = packetBuffer[2]; // PacketNo
D1[4] = packetBuffer[3]; // GameState
D1[5] = packetBuffer[10]; // RaceState
D1[6] = packetBuffer[110]; // CarFlags
D1[7] = packetBuffer[20]; // CurrentTime 1st
D1[8] = packetBuffer[21]; // CurrentTime 2nd
D1[9] = packetBuffer[22]; // CurrentTime 3rd
D1[10] = packetBuffer[23]; // CurrentTime 4th
D1[11] = packetBuffer[120]; // Speed 1st
D1[12] = packetBuffer[121]; // Speed 2nd
D1[13] = packetBuffer[122]; // Speed 3rd
D1[14] = packetBuffer[123]; // Speed 4th
D1[15] = packetBuffer[124]; // Rpm 1st
D1[16] = packetBuffer[125]; // Rpm 2nd
D1[17] = packetBuffer[128]; // GearNumGears
D1[18] = packetBuffer[129]; // Boost
D1[19] = packetBuffer[448]; // EngineSpeed 1st
D1[20] = packetBuffer[449]; // EngineSpeed 2nd
D1[21] = packetBuffer[450]; // EngineSpeed 3rd
D1[22] = packetBuffer[451]; // EngineSpeed 4th
D1[23] = packetBuffer[452]; // Torque 1st
D1[24] = packetBuffer[453]; // Torque 2nd
D1[25] = packetBuffer[454]; // Torque 3rd
D1[26] = packetBuffer[455]; // Torque 4th
D1[27] = packetBuffer[280]; // TyreGrip[0]
D1[28] = packetBuffer[281]; // TyreGrip[1]
D1[29] = packetBuffer[282]; // TyreGrip[2]
D1[30] = packetBuffer[283]; // TyreGrip[3]

// Send D1
delay(1);
Serial.write(D1, 32);

// D2 Dash packet Timer
unsigned long currentMillisD2 = millis();
if (currentMillisD2 - D2oldtime > D2delay) {
D2oldtime = currentMillisD2;
// Serial.println("************************************* Sending Dash D2");
// Prepare D2 Dash packet
D2[3] = packetBuffer[100]; // OilTemp 1st
D2[4] = packetBuffer[101]; // OilTemp 2nd
D2[5] = packetBuffer[102]; // OilPress 1st
D2[6] = packetBuffer[103]; // OilPress 2nd
D2[7] = packetBuffer[104]; // WaterTemp 1st
D2[8] = packetBuffer[105]; // Watertemp 2nd
D2[9] = packetBuffer[106]; // WaterPress 1st
D2[10] = packetBuffer[107]; // WaterPress 2nd
D2[11] = packetBuffer[108]; // FuelPress 1st
D2[12] = packetBuffer[109]; // FuelPress 2nd
D2[13] = packetBuffer[116]; // FuelLevel 1st
D2[14] = packetBuffer[117]; // FuelLevel 2nd
D2[15] = packetBuffer[118]; // FuelLevel 3rd
D2[16] = packetBuffer[119]; // FuelLevel 4th
D2[17] = packetBuffer[130]; // EnforcedPit
D2[18] = packetBuffer[131]; // CrashState
D2[19] = packetBuffer[132]; // OdoKM 1st
D2[20] = packetBuffer[133]; // OdoKM 2nd
D2[21] = packetBuffer[134]; // OdoKM 3rd
D2[22] = packetBuffer[135]; // OdoKM 4th
D2[23] = packetBuffer[456]; // AeroDamage
D2[24] = packetBuffer[457]; // EngineDamage

// Send D2
delay(1);
Serial.write(D2, 26);
}

// D3 Dash packet Timer
unsigned long currentMillisD3 = millis();
if (currentMillisD3 - D3oldtime > D3delay) {
D3oldtime = currentMillisD3;
// Serial.println("************************************* Sending Dash D3");
// Prepare D3 Dash packet
D3[3] = packetBuffer[12]; // BestLapTime 1st
D3[4] = packetBuffer[13]; // BestLapTime 2nd
D3[5] = packetBuffer[14]; // BestLapTime 3rd
D3[6] = packetBuffer[15]; // BestLapTime 4th
D3[7] = packetBuffer[16]; // LastLapTime 1st
D3[8] = packetBuffer[17]; // LastLapTime 2nd
D3[9] = packetBuffer[18]; // LastLapTime 3rd
D3[10] = packetBuffer[19]; // LastLapTime 4th
D3[11] = packetBuffer[40]; // FastestLapTime 1st
D3[12] = packetBuffer[41]; // FastestLapTime 2nd
D3[13] = packetBuffer[42]; // FastestLapTime 3rd
D3[14] = packetBuffer[43]; // FastestLapTime 4th

// Send D3
delay(1);
Serial.write(D3, 16);
}

}

//============================================================================
//= Send a P0, P1 and P2 packet - PartInfo
//============================================================================
void sendPartInfo() {
// Serial.println("*************************************************************======================== Sending PartInfo P0");
if (inGame) {
// P0 - CarName. in[3] out[3]
for (int incount = 3; incount < 67; incount++) {
P0[incount] = packetBuffer[incount];
}
Serial.write(P0, 68);

// P1 - Class. in[67] out[3]
for (int incount = 3; incount < 67; incount++) {
P1[incount] = packetBuffer[(incount+64)];
}
Serial.write(P1, 68);

// P2 - Track. in[131] out[3]
for (int incount = 3; incount < 67; incount++) {
P2[incount] = packetBuffer[(incount+128)];
}
Serial.write(P2, 68);
}
}


//============================================================================
//= Serial print WiFi details
//============================================================================
void printWifiStatus() {
// Serial.print("Network Status: "); Serial.println(wl_status_to_string(WiFi.status()));
// Serial.print("'Status': "); Serial.println(status);

// print the SSID of the network you're attached to:
Serial.print("SSID: "); Serial.println(WiFi.SSID());

// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip);

// print your WiFi shield's MAC address:
WiFi.macAddress(mac);
Serial.print("MAC: ");
Serial.print(mac[0],HEX);
Serial.print(":");
Serial.print(mac[1],HEX);
Serial.print(":");
Serial.print(mac[2],HEX);
Serial.print(":");
Serial.print(mac[3],HEX);
Serial.print(":");
Serial.print(mac[4],HEX);
Serial.print(":");
Serial.println(mac[5],HEX);

// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm");
}

//============================================================================
//= Serial print Racestate
//============================================================================
void raceStatus() {

Serial.println("*********************************************************");
Serial.print("inGame: "); Serial.println(inGame);
Serial.print("practiceStart: "); Serial.println(practiceStart);
Serial.print("raceStart: "); Serial.println(raceStart);
Serial.print("needSetup: "); Serial.println(needSetup);
Serial.print("needPartInfo: "); Serial.println(needPartInfo);
Serial.print("firstRun: "); Serial.println(firstRun);

Serial.print("packetBuffer[3]: "); Serial.println(packetBuffer[3]);
Serial.print("packetBuffer[110]: "); Serial.println(packetBuffer[110]);
}
void WifiConnected() {
digitalWrite(ledPin, HIGH);
}


// END OF PROGRAM





File: data_out.h


// Project Cars UDP data structure
/*
Output fields
P0 = PartInfo - Sent ONLY once, at start of race.
D1, D2, D3, D9, D0 = Dashboard - 1=Every Packet, 2= 1 in 5/10
3= 1 in 50, 9=ChangeState, 0=Start only(P1,P2)
S1 = Suspension Data - Sent EVERY packet

M1,M2,MX, = Motion - XYZ data - 1=Every packet, 2= 1 in 5/10, 9=Change

*/

char packetIsConnectInfo = 'C';
char packetIsPartInfo = 'P';
char packetIsDash = 'D';
char packetIsSusp = 'S';
char packetIsMotion = 'M';

//char startOfPacket = '<'; // 60 = '<'
//char endOfPacket = '>'; // 62 = '>'
byte startOfPacket = 60; // 60 = '<'
byte endOfPacket = 62; // 62 = '>'

// Used to Write Packet Number Out
byte packetNum0 = 0; // Startup Packet - Only sent at start of Race
byte packetNum1 = 1; // Primary data stream. Sent Every packet
byte packetNum2 = 2; // Secondary stream. Sent 1 in 5/10 times
byte packetNum3 = 3; // 3rd stream. Sent 1 in 50/100 times
byte packetNum9 = 9; // Change - Sent on ChangeState
// Connection Packet byte 2
byte C0Disconnect = 0;
byte C0Attempt1 = 1;
byte C0Attempt2 = 2;
byte C0Connect = 3;


//===============================
// C0 - Connection Info
byte C0[4];
//char startOfPacket = < // 0
//char ConnectionC0 // 1
//byte ConnectionC0Num // 2
//char endOfPacket = > // 3
// 4 bytes
//===============================
// P0 - PartInfo_0 CarName - Have to send in 3 packets,cuz serial.write will overflow 128 buffer
byte P0[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '0'
//char CarName[64]; // 3 // 3
//char endOfPacket = > // 67
// 68 byte

//===============================
// P1 - PartInfo_1 Class
byte P1[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '1'
//char CarClassName[64]; // 3 // 67
//char endOfPacket = > // 67
// 68 byte

//===============================
// P2 - PartInfo_2 Track
byte P2[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '2'
//char TrackLocation[64]; // 3 // 131
//char endOfPacket = > // 67
// 68 byte

//===============================
// D0 - Dashboard_0 - Startup parameters - Send ONCE at start of race
byte D0[8];
//char startOfPacket = < // 0
//char Dash_D0; // 1 // 0 = 'D'
//byte Dash_D0Num // 2 // 1 = '0'
//byte LapsInEvent; // 3 // 11
//byte FuelCapacity; // 4 // 111
//unsigned int MaxRpm; // 5 // 126
//char endOfPacket = > // 7
// 8 bytes

//===============================
// D1 - Dashboard_1
byte D1[32];
//char startOfPacket = < // 0
//char Dash_D1; // 1 // 0 = 'D'
//byte Dash_D1Num // 2 // 1 = '1'
//byte PacketNum; // 3 // 2
//byte GameState; // 4 // 3
//byte RaceState; // 5 // 10
//byte CarFlags; // 6 // 110
//float CurrentTime; // 7 // 20
//float Speed; // 11 // 120
//unsigned int Rpm; // 15 // 124
//byte GearNumGears; // 17 // 128
//byte BoostAmount; // 18 // 129
//float EngineSpeed; // 19 // 448
//float EngineTorque; // 23 // 452
//byte TyreGrip[4]; // 27 // 280
//char endOfPacket = > // 31
// 32 bytes

//===============================
// D2 - Dashboard_2
byte D2[26];
//char startOfPacket = < // 0
//char Dash_D2; // 1 // 0 = 'D'
//byte Dash_D2Num // 2 // 1 = '2'
//int OilTempCelsius; // 3 // 100
//unsigned int OilPressureKPa; // 5 // 102
//int WaterTempCelsius; // 7 // 104
//unsigned int WaterPressureKpa; // 9 // 106
//unsigned int FuelPressureKpa; // 11 // 108
//float FuelLevel; // 13 // 116
//char EnforcedPitStopLap; // 17 // 130
//byte CrashState; // 18 // 131
//float OdometerKM; // 19 // 132
//byte AeroDamage; // 23 // 456
//byte EngineDamage; // 24 // 457
//char endOfPacket = > // 25
// 26 bytes

//===============================
// D3 - Dashboard_3
byte D3[16];
//char startOfPacket = < // 0
//char Dash_D3; // 1 // 0 = 'D'
//byte Dash_D3Num // 2 // 1 = '3'
//float BestLapTime; // 3 // 12
//float LastLapTime; // 7 // 16
//float PersonalFastestLapTime; // 11 // 40
//char endOfPacket = > // 15
//16 bytes

//===============================
// D9 - Dashboard_9 - OnChange - Send if data changes
byte D9[15];
//char startOfPacket = < // 0
//char Dash_D9; // 1 // 0 = 'D'
//byte Dash_D9Num // 2 // 1 = '9'
//byte BrakeDamage[4]; // 3 // 320
//byte SuspensionDamage[4]; // 7 // 324
//byte DPad; // 11 // 1366
//unsigned int JoyPad; // 12 // 96
//char endOfPacket = > // 14
// 15bytes

//===============================
// S1 - Suspension - Send EVERY packet
byte S1[84];
//char startOfPacket = < // 0
//char Dash_S1; // 1 // 0 = 'S'
//byte Dash_S1Num // 2 // 1 = '1'
//float TyreHeightAboveGround[4]; // 3 // 284
//float WheelLocalPositionY[4]; // 19 // 376
//float RideHeight[4]; // 35 // 392
//float SuspensionTravel[4]; // 51 // 408
//float SuspensionVelocity[4]; // 67 // 424
//char endOfPacket = > // 83
// 84 bytes

//===============================
// M1 - Motion - Send EVERY packet (WHEN READY i.e. building new seat)
byte M1[124];
//char startOfPacket = < // 0
//char Dash_M1; // 1 // 0 = 'M'
//byte Dash_M1Num // 2 // 1 = '1'
//float Orientation[3]; // 3 // 136
//float LocalVelocity[3]; // 15 // 148
//float WorldVelocity[3]; // 27 // 160
//float AngularVelocity[3]; // 39 // 172
//float LocalAcceleration[3]; // 51 // 184
//float WorldAcceleration[3]; // 63 // 196
//float ExtentsCentre[3]; // 75 // 208
//byte Terrain[4]; // 87 // 224
//float TyreSlipSpeed[4]; // 91 // 260
//float TyreY[4]; // 107 // 228
//char endOfPacket = > // 123
// 124 bytes


//====================================================
// Left over fields from orig 'Wanted'
// Unfiltered input
//byte UnfilteredThrottle; // 6 - 4
//byte UnfilteredBrake; // 7 - 5
//byte UnfilteredSteering; // 8 - 6
//byte UnfilteredClutch; // 9 - 7
// Flags
//byte HighestFlag; // 98 - 28
// Pit info
//byte PitModeSchedule; // 99 - 29
// Car state
//byte Brake; // 112 - 42
//byte Throttle; // 113 - 43
//byte Clutch; // 114 - 44
//char Steering; // 115 - 45
// Wheels / Tyres
//byte TyreFlags[4]; // 220 - 152
//float TyreRPS[4]; // 244 - 176
//float TyreLateralStiffness[4]; // 300 - 228
//byte TyreWear[4]; // 316 - 244
//unsigned int AirPressure[4]; // 440 - 320
// 339 // 1368 struct is padded to
//===============================================================



File: info


/*

Test Versie met led (220 ohm) status op GPIO2

http://forum.projectcarsgame.com/showthread.php?43111-How-to-import-data-from-wifi-into-arduino&highlight=Esp8266 Post 15
Version Control
===============
V1 - Copy of esp8266/WiFiscan & WiFiUDPsendrecievestring merged..
scan for finding Hotspot, udp for UDP.
Recieves packet of size 1367 (Pcars packet size)
V1.1 Tidy code & reformat.
Changed packet size from 255 to 1367.

*V2 - Retrieve packets and move to struct for analysis.
V2.1 Removed Arduino-dash code..
V2.2 Decode ParticipantInfoString
* NOTE - ESP 44% Full...
V3.0 Code cleaned up. All remains or original code removed (udp send, etc)
Tried various way to get fastestlap. serial printed all steps, but always zero...
V3.1 De-code first part of Telemetry to see if gamestate or similar is used to detect if
actually driving, cuz telemetry stream is present all the time..
Only need to write a packet IF driving...
V3.2 Add Multi Network option - For S5 AND Paul Hotspot
Tried MultiAP, but had stack overflow..!!
My version tries S5 5 times, if still no connection, goto next network (Paul)
V3.3 Prepare for serial connection to Teensy
Remove ALL serial prints, and serial.write packetbuffer directl after read.
V4.0 Use SerialStream and Struct....!?!

V5.0 Define smaller packets
Splits data to smaller packets for Serial to Teensy.
GameState and counts done here.
Type 0 = Startup ONLY - Just once at beginning of Race/PitBox
Type 1 = Every Packet
Type 2 = 1 in 5/10 packets - depends on speed
Type 3 = 1 on 20/50 packets - " ditto "
Type 9 = OnChange - (Brk & Sus damage + Dpad & Joypad + ?flags)
V5_1 Decide GameState
If GameState == 17 OR 81
Setup/Prepare for Driving
Send P0 and D0
Else if GameState == 18 & CF Bit 3 = 1
Start Dash - Practice
else if GameState == 82
Start Dash - Race

Added Packet type C for Connection only
V5_2 Testing and fixing Start/Stop data options.
'raceStart' not setting 'needSetup', so had to add 'firstRun'
Practice and Solo QuickRace working. Will probably need to add Career flags later
V5_3_1
'write' packets out.
Connection
PartInfo
D0/D1/D2/D3


Program Desciption
==================
Connects to Hotspot (my S5 or Pauls).
Reads UDP stream on Port 5606. Port 5606 is the default port for Pcars.

I/Os
====
Just ESP8266 at mo.
Rx/Tx - serial (Tx > Tx / Rx > Rx on UNO) - Teensy probably opposite..
*** Move GPIO 0 to Gnd "BEFORE" rebooting, for flash mode.
CH_PD & RST & GPIO2 pulled to VCC with 3k3.
*/


Arduino code (Works on any arduino) this is (currently for DUE)
This wil be in de 2nd post.

Killg0re NL
06-10-2018, 13:17
Arduino code


LEDs:
Light A12 // Head light
ABS A13 // ABS light
ESP A14 // ESP light
TCS A15 // TCS light

Change this to the position where you put the lights on.


Sketchfile: _PC2_Arduino_V1


/*
======================================
= Teensy RX V5.3r (Pcars_udp_rx_v5.3) =
======================================
*/

//============================================================================
//= Libraries
//============================================================================
// Included so 'byte' stops getting 'does not name a type' errors - (Only required because i'm using a Teensy)
//#include <arduino.h>

// Serial Data in - Cut down to required fields
#include "20_Data_in.h"

// Data Extract - fields that Data-in is moved to
#include "20_Data_Extract.h"

// Extra flags not received. For Dashboard setup/control
#include "20_extra_flags.h"

//============================================================================
//= Setup Definitions
//============================================================================
char sketchName[]= "_PC2_Arduino_V1.ino"; // SketchName
char sketchDate[]= "1 july 2018"; // SketchDate

//============================================================================
//= Storage section
//============================================================================
// Incoming Buffer
byte inBuffer[128]; //buffer to hold incoming packet
byte inByte;
char inChar;
bool newPacket = false;

//============================================================================
//= Setup objects
//============================================================================

// Controllable LED's
//#define ledpinRBTN A4 // Encoder Function (not in here yet)
//#define ledpinFuel A11 // FUEL light
#define ledpinLight A12 // Head light (temporarily on A12 instead of A5
#define ledpinABS A13 // ABS light
#define ledpinESP A14 // ESP light
#define ledpinTCS A15 // TCS light
#define ledpinTest 13 // Test light
int ledValOn = 255; // Led brightness Range from 0 to 255

//============================================================================
//= Setup
//============================================================================
void setup() {
// pinMode(ledpinRBTN,OUTPUT);
// pinMode(ledpinFuel,OUTPUT);
pinMode(ledpinLight,OUTPUT);
pinMode(ledpinABS,OUTPUT);
pinMode(ledpinESP,OUTPUT);
pinMode(ledpinTCS,OUTPUT);
pinMode(ledpinTest,OUTPUT);

// initialize serial: For Serial monitor
Serial.begin(115200);
delay(1000);
// initialize serial2: Incoming Data
Serial2.begin(115200);
delay(1000);

// Serial.println();
Serial.println("************************************************************");
Serial.print("Sketch name: "); Serial.println(sketchName);
Serial.print("Sketch date: "); Serial.println(sketchDate);
Serial.println("************************************************************");
}

//===============
// first attempt at a union
union {
byte uBytes[4];
float uFloat;
long uLong;
} uData;

union {
byte sBytes[4];
float sFloat;
long sLong;
} sData;

//============================================================================
//= Main Loop
//============================================================================
void loop() {

// Input serial information:
if (Serial2.available() > 0){
Serial2.readBytesUntil(endOfPacket, inBuffer, 128);
inChar = char(inBuffer[1]);
Serial.print(inChar);
Serial.println(inBuffer[2]);
switch (inChar) {
case 'C':
unpackConnectInfo(); // In rx_Connect.ino
//
break;
case 'P': // Received a PartInfo packet
if (inBuffer[2] < 3) { // Stop spurious P97 packet??
unpackPartInfo(); // In rx_CPartInfo.ino
clearInBuffer();
}
break;
case 'D':
unpackDash();
clearInBuffer();
break;
case 'S':
unpackSusp();
break;
case 'M':
unpackMotion();
break;
}
// clear inBuffer 'PacketType' - see if it stops spurious 8097 packet
// inBuffer[1] = 0;
// inBuffer[2] = 0;
}
}


//============================================================================
//= Unpack Dashboard
//============================================================================
void unpackDash() {

switch (inBuffer[2]) { // packetNum
case 0: // Setup D0
Serial.println("");
LapsInEvent = inBuffer[3];
FuelCapacity = inBuffer[4];
MaxRpm = word(inBuffer[6], inBuffer[5]);
Serial.print("LapsInEvent : "); Serial.println(LapsInEvent);
Serial.print("FuelCapacity : "); Serial.println(FuelCapacity);
Serial.print("MaxRpm : "); Serial.println(MaxRpm);
Serial.println("");
break;
case 1: // Main D1
Serial.println("++");
PacketNum = inBuffer[3];
GameState = inBuffer[4];
RaceState = inBuffer[5];
CarFlags = inBuffer[6];
//Set Flags from Bits..
if (bitRead(CarFlags, 0)) cfLights = true;
else cfLights = false;
if (bitRead(CarFlags, 4)) cfAbs = true;
else cfAbs = false;
if (bitRead(CarFlags, 6)) cfStab = true;
else cfStab = false;
if (bitRead(CarFlags, 7)) cfTrac = true;
else cfTrac = false;
Rpm = word(inBuffer[16], inBuffer[15]);
GearNumGears = inBuffer[17];
currentGear = GearNumGears & 0xf; // & GearNumGears with 00001111(15) to get value of Low4 bits
maxGears = GearNumGears >> 4; // Shift GearNumGears 4 bits Right. Shift out lower 4, leaving only Top 4 bits

BoostAmount = inBuffer[18];
TyreGrip[0] = inBuffer[27];
TyreGrip[1] = inBuffer[28];
TyreGrip[2] = inBuffer[29];
TyreGrip[3] = inBuffer[30];

//debug time
// Serial.print("inBuffer[7] : "); Serial.print(inBuffer[7],DEC);
// Serial.print(" ");Serial.println(inBuffer[7],BIN);
// Serial.print("inBuffer[8] : "); Serial.print(inBuffer[8],DEC);
// Serial.print(" ");Serial.println(inBuffer[8],BIN);
// Serial.print("inBuffer[9] : "); Serial.print(inBuffer[9],DEC);
// Serial.print(" ");Serial.println(inBuffer[9],BIN);
// Serial.print("inBuffer[10] : "); Serial.print(inBuffer[10],DEC);
// Serial.print(" ");Serial.println(inBuffer[10],BIN);

// Move 4 float fields
CurrentTime = (inBuffer[10]) << 24 | (inBuffer[9] & 0xff) << 16 | (inBuffer[8] & 0xff) << 8 | (inBuffer[7] & 0xff);
Speed = (inBuffer[14]) << 24 | (inBuffer[13] & 0xff) << 16 | (inBuffer[12] & 0xff) << 8 | (inBuffer[11] & 0xff);
EngineSpeed = (inBuffer[22]) << 24 | (inBuffer[21] & 0xff) << 16 | (inBuffer[20] & 0xff) << 8 | (inBuffer[19] & 0xff);
EngineTorque = (inBuffer[26]) << 24 | (inBuffer[25] & 0xff) << 16 | (inBuffer[24] & 0xff) << 8 | (inBuffer[23] & 0xff);
// debug speed
// Serial.print("inBuffer[11] : "); Serial.print(inBuffer[11],DEC);
// Serial.print(" ");Serial.println(inBuffer[11],BIN);
// Serial.print("inBuffer[12] : "); Serial.print(inBuffer[12],DEC);
// Serial.print(" ");Serial.println(inBuffer[12],BIN);
// Serial.print("inBuffer[13] : "); Serial.print(inBuffer[13],DEC);
// Serial.print(" ");Serial.println(inBuffer[13],BIN);
// Serial.print("inBuffer[14] : "); Serial.print(inBuffer[14],DEC);
// Serial.print(" ");Serial.println(inBuffer[14],BIN);

// reverse the bits in bytes 11-14, then feed to union
byte byte11Rev = 0;
if (bitRead(inBuffer[11], 0)) bitSet(byte11Rev, 7);
if (bitRead(inBuffer[11], 1)) bitSet(byte11Rev, 6);
if (bitRead(inBuffer[11], 2)) bitSet(byte11Rev, 5);
if (bitRead(inBuffer[11], 3)) bitSet(byte11Rev, 4);
if (bitRead(inBuffer[11], 4)) bitSet(byte11Rev, 3);
if (bitRead(inBuffer[11], 5)) bitSet(byte11Rev, 2);
if (bitRead(inBuffer[11], 6)) bitSet(byte11Rev, 1);
if (bitRead(inBuffer[11], 7)) bitSet(byte11Rev, 0);
byte byte12Rev = 0;
if (bitRead(inBuffer[12], 0)) bitSet(byte12Rev, 7);
if (bitRead(inBuffer[12], 1)) bitSet(byte12Rev, 6);
if (bitRead(inBuffer[12], 2)) bitSet(byte12Rev, 5);
if (bitRead(inBuffer[12], 3)) bitSet(byte12Rev, 4);
if (bitRead(inBuffer[12], 4)) bitSet(byte12Rev, 3);
if (bitRead(inBuffer[12], 5)) bitSet(byte12Rev, 2);
if (bitRead(inBuffer[12], 6)) bitSet(byte12Rev, 1);
if (bitRead(inBuffer[12], 7)) bitSet(byte12Rev, 0);
byte byte13Rev = 0;
if (bitRead(inBuffer[13], 0)) bitSet(byte13Rev, 7);
if (bitRead(inBuffer[13], 1)) bitSet(byte13Rev, 6);
if (bitRead(inBuffer[13], 2)) bitSet(byte13Rev, 5);
if (bitRead(inBuffer[13], 3)) bitSet(byte13Rev, 4);
if (bitRead(inBuffer[13], 4)) bitSet(byte13Rev, 3);
if (bitRead(inBuffer[13], 5)) bitSet(byte13Rev, 2);
if (bitRead(inBuffer[13], 6)) bitSet(byte13Rev, 1);
if (bitRead(inBuffer[13], 7)) bitSet(byte13Rev, 0);
byte byte14Rev = 0;
if (bitRead(inBuffer[14], 0)) bitSet(byte14Rev, 7);
if (bitRead(inBuffer[14], 1)) bitSet(byte14Rev, 6);
if (bitRead(inBuffer[14], 2)) bitSet(byte14Rev, 5);
if (bitRead(inBuffer[14], 3)) bitSet(byte14Rev, 4);
if (bitRead(inBuffer[14], 4)) bitSet(byte14Rev, 3);
if (bitRead(inBuffer[14], 5)) bitSet(byte14Rev, 2);
if (bitRead(inBuffer[14], 6)) bitSet(byte14Rev, 1);
if (bitRead(inBuffer[14], 7)) bitSet(byte14Rev, 0);


// Serial.print("byte11Rev : "); Serial.println(byte11Rev,BIN);
// Serial.print("byte12Rev : "); Serial.println(byte12Rev,BIN);
// Serial.print("byte13Rev : "); Serial.println(byte13Rev,BIN);
// Serial.print("byte14Rev : "); Serial.println(byte14Rev,BIN);


uData.uBytes[0] = inBuffer[11];
uData.uBytes[1] = inBuffer[12];
uData.uBytes[2] = inBuffer[13];
uData.uBytes[3] = inBuffer[14];

sData.sBytes[0] = inBuffer[19];
sData.sBytes[1] = inBuffer[20];
sData.sBytes[2] = inBuffer[21];
sData.sBytes[3] = inBuffer[22];


// uData.uBytes[0] = byte14Rev;
// uData.uBytes[1] = byte13Rev;
// uData.uBytes[2] = byte12Rev;
// uData.uBytes[3] = byte11Rev;

// Serial.print("uBytes [0]-[11] : "); Serial.println(uData.uBytes[0]);
// Serial.print("uBytes [1]-[12] : "); Serial.println(uData.uBytes[1]);
// Serial.print("uBytes [2]-[13] : "); Serial.println(uData.uBytes[2]);
// Serial.print("uBytes [3]-[14] : "); Serial.println(uData.uBytes[3]);
// Serial.print("uFloat : "); Serial.println(uData.uFloat,3);
// Serial.print("uLong : "); Serial.println(uData.uLong);

// Serial.print("sBytes [0]-[19] : "); Serial.println(sData.sBytes[0]);
// Serial.print("sBytes [1]-[20] : "); Serial.println(sData.sBytes[1]);
// Serial.print("sBytes [2]-[21] : "); Serial.println(sData.sBytes[2]);
// Serial.print("sBytes [3]-[22] : "); Serial.println(sData.sBytes[3]);
// Serial.print("sfloat : "); Serial.println(sData.sFloat,3);
// Serial.print("sLong : "); Serial.println(sData.sLong);

// debug
// Serial.print("PacketNum : "); Serial.println(PacketNum);
// Serial.print("GameState : "); Serial.println(GameState);
// Serial.print("RaceState : "); Serial.println(RaceState);
// Serial.print("CarFlags : "); Serial.println(CarFlags);

if (cfAbs) Serial.println(" ABS");
if (cfStab) Serial.println(" ESP");
if (cfTrac) Serial.println(" TCS");

// Serial.print("Rpm : "); Serial.println(Rpm); // Currently not working?
// Serial.print("GearNumGears : "); Serial.println(GearNumGears); // Currently not working?
// Serial.print("BoostAmount : "); Serial.println(BoostAmount); // Currently not working?
// Serial.print("TyreGrip[0] : "); Serial.println(TyreGrip[0]); // Currently not working?
// Serial.print("TyreGrip[1] : "); Serial.println(TyreGrip[1]); // Currently not working?
// Serial.print("TyreGrip[2] : "); Serial.println(TyreGrip[2]); // Currently not working?
// Serial.print("TyreGrip[3] : "); Serial.println(TyreGrip[3]); // Currently not working?
// Serial.print("CurrentTime : "); Serial.println(CurrentTime,3); // Currently not working?
// Serial.print("Speed : "); Serial.println(Speed,3); // Currently not working?
// Serial.print("EngineSpeed : "); Serial.println(EngineSpeed,3); // Currently not working?
// Serial.print("EngineTorque : "); Serial.println(EngineTorque,3); // Currently not working?
// Serial.print("maxGears : "); Serial.println(maxGears);
// Serial.print("currentGear : "); Serial.println(currentGear);
// Serial.print("FuelCapacity : "); Serial.println(FuelLevel); // Currently not working?

// Status Lights

/* Turn leds off when NOT racing (in BETA) GameState X is:
* 17 is exiting Practice (Offline & Online)
* 49 is exiting Qualification (Online, and Offline)
* 81 is exiting Replay, and exiting online Race
*
* 97 is exiting (Offline) TimeTrial,
* but there must be more
* FYI:
* 18 is racing (Online and Offline) practice
* 50 is racing (Online and Offline) qualifing
* 82 is racing (Online abd Offline) Race
*/

if (GameState == 0 || GameState == 17 || GameState == 49 || GameState == 81 || GameState == 97) {
// Serial.println("Turn; Light, ABS, ESP and TCS Off"); //Debug Option
analogWrite(ledpinLight, LOW); // turn Light LED off
analogWrite(ledpinABS, LOW); // turn ABS LED off
analogWrite(ledpinESP, LOW); // turn ESP LED off
analogWrite(ledpinTCS, LOW); // turn TCS LED off
analogWrite(ledpinTest, LOW); // turn TCS LED off
}
else{

// Lights
if (cfLights == true) {
Serial.println("Light ON"); // Debug option
analogWrite(ledpinLight, ledValOn); // turn Light LED on
analogWrite(ledpinTest, ledValOn); // turn Light LED on
}
else {
Serial.println("Light OFF"); // Debug option
digitalWrite(ledpinLight, LOW); // turn Light LED off
digitalWrite(ledpinTest, LOW); // turn Light LED off
}

// ABS
if (cfAbs == true) {
// Serial.println("ABS ON"); // Debug option
analogWrite(ledpinABS, ledValOn); // turn ABS LED on
}
else {
// Serial.println("ABS OFF"); // Debug option
analogWrite(ledpinABS, LOW); // turn ABS LED off
}

// ESP
if (cfStab == true) {
// Serial.println("ESP ON"); // Debug option
analogWrite(ledpinESP, ledValOn); // turn ESP LED on
}
else {
// Serial.println("ESP OFF"); // Debug option
analogWrite(ledpinESP, LOW); // turn ESP LED off
}
// TCS
if (cfTrac == true) {
// Serial.println("TCS ON"); // Debug option
analogWrite(ledpinTCS, ledValOn); // turn TCS LED on
}
else {
// Serial.println("TCS OFF"); // Debug option
analogWrite(ledpinTCS, LOW); // turn TCS LED off
}
}

Serial.println("");
break;
// case 2:
// Serial.println("++++Received D2 ");
// break;
// case 3:
// Serial.println("++++Received D3 ");
// break;
}
}




//============================================================================
//= Unpack Suspension
//============================================================================
void unpackSusp() {
// Serial.println("void unpackSusp"); // Debug

}

//============================================================================
//= Unpack Motion
//============================================================================
void unpackMotion() {
// Serial.println(" void unpackMotion"); // Debug


}

//============================================================================
//= Unpack Motion
//============================================================================
void clearInBuffer() {
for (int countCLR = 0; countCLR < 128; countCLR++) {
inBuffer[countCLR] = 0;
// Serial.println(" void clearInBuffer"); // Debug
}

}

// END OF CODE ================================================
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = =


file: 20_Data_Extract.h


//===============================
// C0 - Connection Info
//byte C0[4];
//char startOfPacket = < // 0
//char ConnectionC0 // 1
//byte ConnectionC0Num // 2
//char endOfPacket = > // 3
// 4 bytes
//===============================
// P0 - PartInfo_0 CarName - Have to send in 3 packets,cuz serial.write will overflow 128 buffer
//byte P0[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '0'
char CarName[64]; // 3 // 3
//char endOfPacket = > // 67
// 68 byte

//===============================
// P1 - PartInfo_1 Class
//byte P1[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '1'
char CarClassName[64]; // 3 // 67
//char endOfPacket = > // 67
// 68 byte

//===============================
// P2 - PartInfo_2 Track
//byte P2[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '2'
char TrackLocation[64]; // 3 // 131
//char endOfPacket = > // 67
// 68 byte

//===============================
// D0 - Dashboard_0 - Startup parameters - Send ONCE at start of race
//byte D0[8];
//char startOfPacket = < // 0
//char Dash_D0; // 1 // 0 = 'D'
//byte Dash_D0Num // 2 // 1 = '0'
byte LapsInEvent; // 3 // 11
byte FuelCapacity; // 4 // 111
unsigned int MaxRpm; // 5 // 126
//char endOfPacket = > // 7
// 8 bytes

//===============================
// D1 - Dashboard_1
//byte D1[32];
//char startOfPacket = < // 0
//char Dash_D1; // 1 // 0 = 'D'
//byte Dash_D1Num // 2 // 1 = '1'
byte PacketNum; // 3 // 2
byte GameState; // 4 // 3
byte RaceState; // 5 // 10
byte CarFlags; // 6 // 110
float CurrentTime; // 7 // 20
float Speed; // 11 // 120
unsigned int Rpm; // 15 // 124
byte GearNumGears; // 17 // 128
byte BoostAmount; // 18 // 129
float EngineSpeed; // 19 // 448
float EngineTorque; // 23 // 452
byte TyreGrip[4]; // 27 // 280
//char endOfPacket = > // 31
// 32 bytes

//===============================
// D2 - Dashboard_2
//byte D2[26];
//char startOfPacket = < // 0
//char Dash_D2; // 1 // 0 = 'D'
//byte Dash_D2Num // 2 // 1 = '2'
int OilTempCelsius; // 3 // 100
unsigned int OilPressureKPa; // 5 // 102
int WaterTempCelsius; // 7 // 104
unsigned int WaterPressureKpa; // 9 // 106
unsigned int FuelPressureKpa; // 11 // 108
float FuelLevel; // 13 // 116
char EnforcedPitStopLap; // 17 // 130
byte CrashState; // 18 // 131
float OdometerKM; // 19 // 132
byte AeroDamage; // 23 // 456
byte EngineDamage; // 24 // 457
//char endOfPacket = > // 25
// 26 bytes

//===============================
// D3 - Dashboard_3
//byte D3[16];
//char startOfPacket = < // 0
//char Dash_D3; // 1 // 0 = 'D'
//byte Dash_D3Num // 2 // 1 = '3'
float BestLapTime; // 3 // 12
float LastLapTime; // 7 // 16
float PersonalFastestLapTime; // 11 // 40
//char endOfPacket = > // 15
//16 bytes

//===============================
// D9 - Dashboard_9 - OnChange - Send if data changes
//byte D9[15];
//char startOfPacket = < // 0
//char Dash_D9; // 1 // 0 = 'D'
//byte Dash_D9Num // 2 // 1 = '9'
byte BrakeDamage[4]; // 3 // 320
byte SuspensionDamage[4]; // 7 // 324
byte DPad; // 11 // 1366
unsigned int JoyPad; // 12 // 96
//char endOfPacket = > // 14
// 15bytes

//===============================
// S1 - Suspension - Send EVERY packet
//byte S1[84];
//char startOfPacket = < // 0
//char Dash_S1; // 1 // 0 = 'S'
//byte Dash_S1Num // 2 // 1 = '1'
float TyreHeightAboveGround[4]; // 3 // 284
float WheelLocalPositionY[4]; // 19 // 376
float RideHeight[4]; // 35 // 392
float SuspensionTravel[4]; // 51 // 408
float SuspensionVelocity[4]; // 67 // 424
//char endOfPacket = > // 83
// 84 bytes

//===============================
// M1 - Motion - Send EVERY packet (WHEN READY i.e. building new seat)
//byte M1[124];
//char startOfPacket = < // 0
//char Dash_M1; // 1 // 0 = 'M'
//byte Dash_M1Num // 2 // 1 = '1'
float Orientation[3]; // 3 // 136
float LocalVelocity[3]; // 15 // 148
float WorldVelocity[3]; // 27 // 160
float AngularVelocity[3]; // 39 // 172
float LocalAcceleration[3]; // 51 // 184
float WorldAcceleration[3]; // 63 // 196
float ExtentsCentre[3]; // 75 // 208
byte Terrain[4]; // 87 // 224
float TyreSlipSpeed[4]; // 91 // 260
float TyreY[4]; // 107 // 228
//char endOfPacket = > // 123
// 124 bytes


file: 20_Data_in.h


// Project Cars UDP data structure
/*
Output fields
P0 = PartInfo - Sent ONLY once, at start of race.
D1, D2, D3, D9, D0 = Dashboard - 1=Every Packet, 2= 1 in 5/10
3= 1 in 50, 9=ChangeState, 0=Start only(P1,P2)
S1 = Suspension Data - Sent EVERY packet

M1,M2,MX, = Motion - XYZ data - 1=Every packet, 2= 1 in 5/10, 9=Change

*/

//char packetType; // Used to Write Packet Type Out
char packetIsConnectInfo = 'C';
char packetIsPartInfo = 'P';
char packetIsDash = 'D';
char packetIsSusp = 'S';
char packetIsMotion = 'M';

//char startOfPacket = '<'; // 60 = '<'
//char endOfPacket = '>'; // 62 = '>'
byte startOfPacket = 60; // 60 = '<'
byte endOfPacket = 62; // 62 = '>'

// Used to Write Packet Number Out
byte packetNum0 = 0; // Startup Packet - Only sent at start of Race
byte packetNum1 = 1; // Primary data stream. Sent Every packet
byte packetNum2 = 2; // Secondary stream. Sent 1 in 5/10 times
byte packetNum3 = 3; // 3rd stream. Sent 1 in 50/100 times
byte packetNum9 = 9; // Change - Sent on ChangeState
// Connection Packet byte 2
byte C0Disconnect = 0;
byte C0Attempt1 = 1;
byte C0Attempt2 = 2;
byte C0Connect = 3;


//===============================
// C0 - Connection Info
byte C0[4];
//char startOfPacket = < // 0
//char ConnectionC0 // 1
//byte ConnectionC0Num // 2
//char endOfPacket = > // 3
// 4 bytes
//===============================
// P0 - PartInfo_0 CarName - Have to send in 3 packets,cuz serial.write will overflow 128 buffer
byte P0[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '0'
//char CarName[64]; // 3 // 3
//char endOfPacket = > // 67
// 68 byte

//===============================
// P1 - PartInfo_1 Class
byte P1[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '1'
//char CarClassName[64]; // 3 // 67
//char endOfPacket = > // 67
// 68 byte

//===============================
// P2 - PartInfo_2 Track
byte P2[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '2'
//char TrackLocation[64]; // 3 // 131
//char endOfPacket = > // 67
// 68 byte

//===============================
// D0 - Dashboard_0 - Startup parameters - Send ONCE at start of race
byte D0[8];
//char startOfPacket = < // 0
//char Dash_D0; // 1 // 0 = 'D'
//byte Dash_D0Num // 2 // 1 = '0'
//byte LapsInEvent; // 3 // 11
//byte FuelCapacity; // 4 // 111
//unsigned int MaxRpm; // 5 // 126
//char endOfPacket = > // 7
// 8 bytes

//===============================
// D1 - Dashboard_1
byte D1[32];
//char startOfPacket = < // 0
//char Dash_D1; // 1 // 0 = 'D'
//byte Dash_D1Num // 2 // 1 = '1'
//byte PacketNum; // 3 // 2
//byte GameState; // 4 // 3
//byte RaceState; // 5 // 10
//byte CarFlags; // 6 // 110
//float CurrentTime; // 7 // 20
//float Speed; // 11 // 120
//unsigned int Rpm; // 15 // 124
//byte GearNumGears; // 17 // 128
//byte BoostAmount; // 18 // 129
//float EngineSpeed; // 19 // 448
//float EngineTorque; // 23 // 452
//byte TyreGrip[4]; // 27 // 280
//char endOfPacket = > // 31
// 32 bytes

//===============================
// D2 - Dashboard_2
byte D2[26];
//char startOfPacket = < // 0
//char Dash_D2; // 1 // 0 = 'D'
//byte Dash_D2Num // 2 // 1 = '2'
//int OilTempCelsius; // 3 // 100
//unsigned int OilPressureKPa; // 5 // 102
//int WaterTempCelsius; // 7 // 104
//unsigned int WaterPressureKpa; // 9 // 106
//unsigned int FuelPressureKpa; // 11 // 108
//float FuelLevel; // 13 // 116
//char EnforcedPitStopLap; // 17 // 130
//byte CrashState; // 18 // 131
//float OdometerKM; // 19 // 132
//byte AeroDamage; // 23 // 456
//byte EngineDamage; // 24 // 457
//char endOfPacket = > // 25
// 26 bytes

//===============================
// D3 - Dashboard_3
byte D3[16];
//char startOfPacket = < // 0
//char Dash_D3; // 1 // 0 = 'D'
//byte Dash_D3Num // 2 // 1 = '3'
//float BestLapTime; // 3 // 12
//float LastLapTime; // 7 // 16
//float PersonalFastestLapTime; // 11 // 40
//char endOfPacket = > // 15
//16 bytes

//===============================
// D9 - Dashboard_9 - OnChange - Send if data changes
byte D9[15];
//char startOfPacket = < // 0
//char Dash_D9; // 1 // 0 = 'D'
//byte Dash_D9Num // 2 // 1 = '9'
//byte BrakeDamage[4]; // 3 // 320
//byte SuspensionDamage[4]; // 7 // 324
//byte DPad; // 11 // 1366
//unsigned int JoyPad; // 12 // 96
//char endOfPacket = > // 14
// 15bytes

//===============================
// S1 - Suspension - Send EVERY packet
byte S1[84];
//char startOfPacket = < // 0
//char Dash_S1; // 1 // 0 = 'S'
//byte Dash_S1Num // 2 // 1 = '1'
//float TyreHeightAboveGround[4]; // 3 // 284
//float WheelLocalPositionY[4]; // 19 // 376
//float RideHeight[4]; // 35 // 392
//float SuspensionTravel[4]; // 51 // 408
//float SuspensionVelocity[4]; // 67 // 424
//char endOfPacket = > // 83
// 84 bytes

//===============================
// M1 - Motion - Send EVERY packet (WHEN READY i.e. building new seat)
byte M1[124];
//char startOfPacket = < // 0
//char Dash_M1; // 1 // 0 = 'M'
//byte Dash_M1Num // 2 // 1 = '1'
//float Orientation[3]; // 3 // 136
//float LocalVelocity[3]; // 15 // 148
//float WorldVelocity[3]; // 27 // 160
//float AngularVelocity[3]; // 39 // 172
//float LocalAcceleration[3]; // 51 // 184
//float WorldAcceleration[3]; // 63 // 196
//float ExtentsCentre[3]; // 75 // 208
//byte Terrain[4]; // 87 // 224
//float TyreSlipSpeed[4]; // 91 // 260
//float TyreY[4]; // 107 // 228
//char endOfPacket = > // 123
// 124 bytes


file: 20_extra_flags.h


//=================================
// DashBoard Extra flags. Not received, just for processing here
bool ignitionOn = false; // Read RPM - If last rpm was 0, now >0 Ign ON
bool startUp = false; // Use to run dash startup seq
bool lightsOn = false; // read from carFlags
bool absOn = false; // read from carFlags - 3 bits in carFlags change
bool tractionOn = false; // read from carFlags - find out which is which
bool stabilityOn = false; // read from carFlags - if its there..

// RPM = int, enginespeed = float. Not sure which yet
// float lastRPM = 0; // Hold last RPM value
// int lastRPM = 0; // Hold last RPM value

//=================================
// wifiLED status. No connect=Off, Attempt=Flash, Connected=Solid
bool wifiLEDattempt = false; // WiFi Status - attempting - Flash
bool wifiLEDconnect = false; // WiFi Status - connected - Solid
bool connectS5 = false;
bool connectPaul = false;

long currentTimeLong = 0;
long speedLong = 0;
long engineSpeedLong = 0;
long engineTorqueLong = 0;

byte maxGears;
byte currentGear;

bool cfLights = false;
bool cfAbs = false;
bool cfStab = false;
bool cfTrac = false;


file: data_out.h


// Project Cars UDP data structure
/*
Output fields
P0 = PartInfo - Sent ONLY once, at start of race.
D1, D2, D3, D9, D0 = Dashboard - 1=Every Packet, 2= 1 in 5/10
3= 1 in 50, 9=ChangeState, 0=Start only(P1,P2)
S1 = Suspension Data - Sent EVERY packet

M1,M2,MX, = Motion - XYZ data - 1=Every packet, 2= 1 in 5/10, 9=Change

*/

//char packetType; // Used to Write Packet Type Out
char packetIsConnectInfo = 'C';
char packetIsPartInfo = 'P';
char packetIsDash = 'D';
char packetIsSusp = 'S';
char packetIsMotion = 'M';

//char startOfPacket = '<'; // 60 = '<'
//char endOfPacket = '>'; // 62 = '>'
byte startOfPacket = 60; // 60 = '<'
byte endOfPacket = 62; // 62 = '>'

// Used to Write Packet Number Out
byte packetNum0 = 0; // Startup Packet - Only sent at start of Race
byte packetNum1 = 1; // Primary data stream. Sent Every packet
byte packetNum2 = 2; // Secondary stream. Sent 1 in 5/10 times
byte packetNum3 = 3; // 3rd stream. Sent 1 in 50/100 times
byte packetNum9 = 9; // Change - Sent on ChangeState
// Connection Packet byte 2
byte C0Disconnect = 0;
byte C0Attempt1 = 1;
byte C0Attempt2 = 2;
byte C0Connect = 3;


//===============================
// C0 - Connection Info
byte C0[4];
//char startOfPacket = < // 0
//char ConnectionC0 // 1
//byte ConnectionC0Num // 2
//char endOfPacket = > // 3
// 4 bytes
//===============================
// P0 - PartInfo_0 CarName - Have to send in 3 packets,cuz serial.write will overflow 128 buffer
byte P0[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '0'
//char CarName[64]; // 3 // 3
//char endOfPacket = > // 67
// 68 byte

//===============================
// P1 - PartInfo_1 Class
byte P1[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '1'
//char CarClassName[64]; // 3 // 67
//char endOfPacket = > // 67
// 68 byte

//===============================
// P2 - PartInfo_2 Track
byte P2[68];
//char startOfPacket = < // 0
//char PartInfoP0; // 1 // 0 = 'P'
//byte PartInfoP0Num // 2 // 1 = '2'
//char TrackLocation[64]; // 3 // 131
//char endOfPacket = > // 67
// 68 byte

//===============================
// D0 - Dashboard_0 - Startup parameters - Send ONCE at start of race
byte D0[8];
//char startOfPacket = < // 0
//char Dash_D0; // 1 // 0 = 'D'
//byte Dash_D0Num // 2 // 1 = '0'
//byte LapsInEvent; // 3 // 11
//byte FuelCapacity; // 4 // 111
//unsigned int MaxRpm; // 5 // 126
//char endOfPacket = > // 7
// 8 bytes

//===============================
// D1 - Dashboard_1
byte D1[32];
//char startOfPacket = < // 0
//char Dash_D1; // 1 // 0 = 'D'
//byte Dash_D1Num // 2 // 1 = '1'
//byte PacketNum; // 3 // 2
//byte GameState; // 4 // 3
//byte RaceState; // 5 // 10
//byte CarFlags; // 6 // 110
//float CurrentTime; // 7 // 20
//float Speed; // 11 // 120
//unsigned int Rpm; // 15 // 124
//byte GearNumGears; // 17 // 128
//byte BoostAmount; // 18 // 129
//float EngineSpeed; // 19 // 448
//float EngineTorque; // 23 // 452
//byte TyreGrip[4]; // 27 // 280
//char endOfPacket = > // 31
// 32 bytes

//===============================
// D2 - Dashboard_2
byte D2[26];
//char startOfPacket = < // 0
//char Dash_D2; // 1 // 0 = 'D'
//byte Dash_D2Num // 2 // 1 = '2'
//int OilTempCelsius; // 3 // 100
//unsigned int OilPressureKPa; // 5 // 102
//int WaterTempCelsius; // 7 // 104
//unsigned int WaterPressureKpa; // 9 // 106
//unsigned int FuelPressureKpa; // 11 // 108
//float FuelLevel; // 13 // 116
//char EnforcedPitStopLap; // 17 // 130
//byte CrashState; // 18 // 131
//float OdometerKM; // 19 // 132
//byte AeroDamage; // 23 // 456
//byte EngineDamage; // 24 // 457
//char endOfPacket = > // 25
// 26 bytes

//===============================
// D3 - Dashboard_3
byte D3[16];
//char startOfPacket = < // 0
//char Dash_D3; // 1 // 0 = 'D'
//byte Dash_D3Num // 2 // 1 = '3'
//float BestLapTime; // 3 // 12
//float LastLapTime; // 7 // 16
//float PersonalFastestLapTime; // 11 // 40
//char endOfPacket = > // 15
//16 bytes

//===============================
// D9 - Dashboard_9 - OnChange - Send if data changes
byte D9[15];
//char startOfPacket = < // 0
//char Dash_D9; // 1 // 0 = 'D'
//byte Dash_D9Num // 2 // 1 = '9'
//byte BrakeDamage[4]; // 3 // 320
//byte SuspensionDamage[4]; // 7 // 324
//byte DPad; // 11 // 1366
//unsigned int JoyPad; // 12 // 96
//char endOfPacket = > // 14
// 15bytes

//===============================
// S1 - Suspension - Send EVERY packet
byte S1[84];
//char startOfPacket = < // 0
//char Dash_S1; // 1 // 0 = 'S'
//byte Dash_S1Num // 2 // 1 = '1'
//float TyreHeightAboveGround[4]; // 3 // 284
//float WheelLocalPositionY[4]; // 19 // 376
//float RideHeight[4]; // 35 // 392
//float SuspensionTravel[4]; // 51 // 408
//float SuspensionVelocity[4]; // 67 // 424
//char endOfPacket = > // 83
// 84 bytes

//===============================
// M1 - Motion - Send EVERY packet (WHEN READY i.e. building new seat)
byte M1[124];
//char startOfPacket = < // 0
//char Dash_M1; // 1 // 0 = 'M'
//byte Dash_M1Num // 2 // 1 = '1'
//float Orientation[3]; // 3 // 136
//float LocalVelocity[3]; // 15 // 148
//float WorldVelocity[3]; // 27 // 160
//float AngularVelocity[3]; // 39 // 172
//float LocalAcceleration[3]; // 51 // 184
//float WorldAcceleration[3]; // 63 // 196
//float ExtentsCentre[3]; // 75 // 208
//byte Terrain[4]; // 87 // 224
//float TyreSlipSpeed[4]; // 91 // 260
//float TyreY[4]; // 107 // 228
//char endOfPacket = > // 123
// 124 bytes


//====================================================
// Left over fields from orig 'Wanted'
// Unfiltered input
//byte UnfilteredThrottle; // 6 - 4
//byte UnfilteredBrake; // 7 - 5
//byte UnfilteredSteering; // 8 - 6
//byte UnfilteredClutch; // 9 - 7
// Flags
//byte HighestFlag; // 98 - 28
// Pit info
//byte PitModeSchedule; // 99 - 29
// Car state
//byte Brake; // 112 - 42
//byte Throttle; // 113 - 43
//byte Clutch; // 114 - 44
//char Steering; // 115 - 45
// Wheels / Tyres
//byte TyreFlags[4]; // 220 - 152
//float TyreRPS[4]; // 244 - 176
//float TyreLateralStiffness[4]; // 300 - 228
//byte TyreWear[4]; // 316 - 244
//unsigned int AirPressure[4]; // 440 - 320
// 339 // 1368 struct is padded to
//===============================================================


file: info


/*
ANALOG IN/OUTPUT:
A0 - i - Keypad Column 1
A1 - i - Keypad Column 2
A2 - i - Keypad Column 3
A3 - i - Keypad Column 4
A4 - o - Led Encoder Function
A5 - o - Led Headlight
A6 (DUE)- o - Led ABS
A7 (DUE)- o - Led ESP
A8 (DUE)- o - Led TCS
A9 (DUE)- o - Led Fuel
A10(DUE)- i/o -
A11(DUE)- i/o -

DIGITAL IN/OUTPUT
0 (RX) - i - Reserved for serial(0) interface
1 (TX) - i - Reserved for serial(0) interface
2 - i - Keypad Row 1
3 - i - Keypad Row 2
4 - i - Keypad Row 3
5 - i - Keypad Row 4
6 - i - Encoder 1a
7 - i - Encoder 1b
8 - i - Encoder 2a
9 - i - Encoder 2b
10 - i - Encoder 3a
11 - i - Encoder 3b
12 - i - Encoder 4a
13 - i - Encoder 4b
14(DUE) - i/o - Reserved for serial(3)
15(DUE) - i/o - Reserved for serial(3)
16(DUE) - i/o - Reserved for serial(2)
17(DUE) - i/o - Reserved for serial(2)
18(DUE) - i/o - Reserved for serial(1)
19(DUE) - i/o - Reserved for serial(1)
20(DUE) - i/o - Reserved for SDA
21(DUE) - i/o - Reserved for SCL
22(DUE) - i/o -
23(DUE) - i/o -
24(DUE) - i/o -
25(DUE) - i/o -
26(DUE) - i/o -
27(DUE) - i/o -
28(DUE) - i/o -
29(DUE) - i/o -
30(DUE) - i/o -
and 31 to 53

Version Control
===============
V1 - Copy of serialEvent example, but completely changed.
V4.01 - Waits for 'startofpacket', then reads next byte (hijacked)
Then, now on byte 2, reads fixed length buffer into
temp buffer (one less than original, cuz its read twice
Then.. Moves temp buffer to full buffer
V5.3 - Use ReadbyteUntil



Program Desciption
==================
Reads Serial2 for startofpacket ("<")
Moves next 1367 bytes to inBuffer, unless EOF (">")
Once a full packet is received
Test for packet type using hijacked byte [0].
"P" = PartInfo
"T" = Telemetry

I/Os
====
ESP8266 incoming on Serial2 (Tx=10,Rx=9).
*/


file: rx_Connect


//============================================================================
//= Unpack Connection Info
//============================================================================
// Future- Add LED to Teensy or Display on screen
void unpackConnectInfo() {

Serial.print(inBuffer[1]); Serial.println(inBuffer[2]);

// If NO connection (byte 2 == 0)
if (inBuffer[2] == 0) {
Serial.println("No Connection");
connectS5 = false;
connectPaul = false;
}

// If Attempting SSID 1 (byte 2 == 1)
else if (inBuffer[2] == 1) {
Serial.println("Attempting to connect to first Network");
connectS5 = true; // Set
connectPaul = false;
}

// If Attempting SSID 2 (byte 2 == 2)
else if (inBuffer[2] == 2) {
Serial.println("Attempting to connect to second Network");
connectS5 = false;
connectPaul = true;
}
// If Connection Successful (byte 2 == 3) use connect flags to show which
else if (inBuffer[2] == 3) {
if (connectS5) Serial.println("Successfully Connected to TOFNET");
if (connectPaul) Serial.println("Successfully Connected to TOFNET-5G");
}

} // END OF unpackConnectInfo


file: rx_PartInfo


//============================================================================
//= Unpack PartInfo
//============================================================================
void unpackPartInfo() {

// debug - print buffer code
Serial.print(inBuffer[1]); Serial.println(inBuffer[2]);

switch (inBuffer[2]) {
case 0:
for (int count = 0; count < 64; count++) {
CarName[count] = inBuffer[(count+3)];
}
Serial.print("CarName : "); Serial.println(CarName);
break;
case 1:
for (int count = 0; count < 64; count++) {
CarClassName[count] = inBuffer[(count+3)];
}
Serial.print("CarClassName : "); Serial.println(CarClassName);
break;
case 2:
for (int count = 0; count < 64; count++) {
TrackLocation[count] = inBuffer[(count+3)];
}
Serial.print("TrackLocation : "); Serial.println(TrackLocation);
break;
}
} // END OF unpackPartInfo

Killg0re NL
06-10-2018, 13:17
1st post contains the link an code for the ESP8266
2nd post contains the code for the Arduino

Future plans are to put this code straight on a single ESP32
And this can be used together with the Buttonbox LINK (http://forum.projectcarsgame.com/showthread.php?61987-DIY-Buttonbox-V1b-15-switches-and-8-encoder-functions&highlight=buttonbox)

VelvetTorpedo
07-10-2018, 13:38
Eagerly waiting for esp32 version :)

Killg0re NL
24-03-2019, 20:05
See here what i got so far for the ESP32 version, the sketch is prototol independend, so it doesn't matter if it is on Project Cars 1 or 2 protocol.

And for me, it can use the following hardware:

TM1637
TM1638
LCD (2x16)
serveral (RGB) Leds


Not all is fully functional, but you can work onwards frome here.

When somebody knows how to get the FuelLevel in de UDP2 version working, advice is apreciated


_PC2_ESP32_V1Forum.ino


//============================================================================
//= Libraries
//============================================================================
#include <WiFi.h> // ESP32 Wifi
#include <WiFiUdp.h> // Standard Wifi UDP Lib
#include <Wire.h> // Wire.h for the MCP

// MCP
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp1; // Refer to 1st MCP23017 as mcp1
#define addr1 0 // use address 0 ; 0x20=adress 0, 0x21=1 and so on

//Adafruit_MCP23017 mcp2; // Refer to 2nd MCP23017 as mcp2
//#define addr2 1 // use address 1

//LCD Display
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd1(0x3f, 16, 2); // set the i2c LCD address to 0x3F for a 16 chars and 2 line display

//============================================================================
//= WiFi fields
//============================================================================

char ssid[] = "putSSIDhere"; // your network SSID (name)
char pass[] = "puPASSWORDhere"; // your network password (use for WPA, or use as key for WEP)
byte mac[6]; // the MAC address of your Wifi shield

// Setup Definitions
char sketchName[] = "ESP32_V1_Forum"; // SketchName
char sketchDate[] = "24 mar 19"; // SketchDate

//============================================================================
//= Hardware in / outputs (board order)
//============================================================================
boolean ledState = true; // Wifi Status led (status is allready in use)

int ledpinWiFi = 2; // GPIO 2

// MCP 1: GPA0 = 0, GPA7 = 7, GPB0 = 8, GPB7 = 15
#define mcp1ledpinWiFi 0 // Led on MCP1 GPA0
#define mcp1ledpinABS 1 // Led on MCP1 GPA1
#define mcp1ledpinESP 2 // Led on MCP1 GPA2
#define mcp1ledpinTCS 3 // Led on MCP1 GPA3
#define mcp1ledpinLight 4 // Led on MCP1 GPA4
#define mcp1ledpinOilTemp 5 // Led on MCP1 GPA5
#define mcp1ledpinPit 6 // Led on MCP1 GPA6
#define mcp1ledpinFuel 7 // Led on MCP1 GPA7

#define mcp1ledpinRGBR 8 // Led on MCP1 GPB0
#define mcp1ledpinRGBG 9 // Led on MCP1 GPB1
#define mcp1ledpinRGBB 10 // Led on MCP1 GPB2
//#define mcp1ledpinGPB3 11 // Led on MCP1 GPB3
//#define mcp1ledpinGPB4 12 // Led on MCP1 GPB4
//#define mcp1ledpinGPB5 13 // Led on MCP1 GPB5
//#define mcp1ledpinGPB6 14 // Led on MCP1 GPB6
//#define mcp1ledpinGPB7 15 // Led on MCP1 GPB7


//============================================================================
//= Setup objects
//============================================================================
#include "0_pc.h" // Project Cars init
#include "void_PC2.h"
#include "void_WiFi.h"
#include "2L_out.h" // Arduino Loop, output
#include "2L_0_pc.h" // Arduino Loop, actual
#include "2L_2_flags.h" // Arduino Loop, For setting flags (Currently not used)
#include "2L_debug.h" // Debug / experiment part

WiFiUDP Udp; // Create UDP object

//============================================================================
//= Setup
//============================================================================
void setup() {

mcp1.begin(addr1); // using adress declared @ addr1 and addr2
//mcp2.begin(addr2); // using adress declared @ addr1 and addr2
module1637_1.setBrightness(0x0a); // set the 1637-1 diplay to maximum brightness

Serial.begin(115200);
delay(500);
Serial.println();
Serial.println("************************************************************");
Serial.print ("Sketch name : "); Serial.println(sketchName);
Serial.print ("Sketch date : "); Serial.println(sketchDate);
Serial.print ("Sketch details: "); Serial.println("i2c, TM1637/38, UDP (PC1 & PC2)");
Serial.println("************************************************************");
// module1.setDisplayToString("--------");
// module1.clearDisplay();

// set up the LCD's number of columns and rows:
lcd1.init();
lcd1.backlight();
lcd1.clear();
lcd1.setCursor(0, 0); lcd1.print(sketchName);
lcd1.setCursor(0, 1); lcd1.print(sketchDate);

mcp1.pinMode(mcp1ledpinWiFi, OUTPUT);
mcp1.pinMode(mcp1ledpinLight, OUTPUT);
mcp1.pinMode(mcp1ledpinABS, OUTPUT);
mcp1.pinMode(mcp1ledpinTCS, OUTPUT);
mcp1.pinMode(mcp1ledpinESP, OUTPUT);
mcp1.pinMode(mcp1ledpinPit, OUTPUT);
mcp1.pinMode(mcp1ledpinOilTemp, OUTPUT);
mcp1.pinMode(mcp1ledpinRGBR, OUTPUT);
mcp1.pinMode(mcp1ledpinRGBG, OUTPUT);
mcp1.pinMode(mcp1ledpinRGBB, OUTPUT);
mcp1.pinMode(mcp1ledpinFuel, OUTPUT);
pinMode(ledpinWiFi, OUTPUT);
digitalWrite(ledpinWiFi, LOW);

ledTest(); //Void ledTest
WiFiConnect(); //Void WiFiConnect

//============================================================================
//= Start of UDP
//============================================================================
// Serial.println("UDP Begin");
Udp.begin(localPort);
}

//============================================================================
//= Main Loop
//============================================================================
void loop() {
if (WiFi.status() != WL_CONNECTED)
{
} else { // Wifi Connection Established, so begin Program / Sketch

// If data available, read a packet
int packetSize = Udp.parsePacket(); // Reads the size of the UDP package
// DEBUG : Prints the recieved packetSize of the UDP package
// Serial.print("Recieved Packetsize :") ;Serial.println(packetSize);
// delay(100);


// UDP Project Cars 2 Protocol
if (packetSize == sTelemetryPC2) { // PC2 Packet?
Udp.read(packetBuffer, 559); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 559
//Serial.println(" Packetbuffer 559 recieved");
digitalWrite(ledpinWiFi, !digitalRead(ledpinWiFi)); // Toggle / Flash Onboard WiFi LED
udp559(); // Witch output (i.e. LED's) is set, under what circumstances
carflags();
carflagsout();
}

else if (packetSize == sTimingsDataPC2) { // PC2 Packet
Udp.read(packetBuffer, 1063); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 1063
//Serial.println(" Packetbuffer 1063 recieved");
//udp1063(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sParticipantsDataPC2) { // PC2 Packet
Udp.read(packetBuffer, 1136); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 1164
//Serial.println(" Packetbuffer 1136 recieved");
udp1136(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sParticipantVehicleNamesDataPC2) { // PC2 Packet
Udp.read(packetBuffer, 1164); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 1164
//Serial.println(" Packetbuffer 1164 recieved");
//udp1164(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sVehicleClassNamesDataPC2) { // PC2 Packet
Udp.read(packetBuffer, 1452); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 1452
//Serial.println(" Packetbuffer 1452 recieved");
//udp1452(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sGameStateDataPC2) { // PC2 Packet
Udp.read(packetBuffer, 24); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 24
//Serial.println(" Packetbuffer 24 recieved");
udp24(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sTimeStatsDataPC2) { // PC2 Packet
Udp.read(packetBuffer, 1024); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 1024
//Serial.println(" Packetbuffer 1024 recieved");
//udp1024(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sParticipantsStatsPC2) { // PC2 Packet
Udp.read(packetBuffer, 1040); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 1040
//Serial.println(" Packetbuffer 1040 recieved");
//udp1040(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sRaceDataPC2) { // PC2 Packet
Udp.read(packetBuffer, 308); // Read the Project Cars 2 protocol UDP packet, and put in it packetBuffer 308
//Serial.println(" Packetbuffer 1308 recieved");
//udp308(); // Witch output (i.e. LED's) is set, under what circumstances

}

// UDP Project Cars 1 Protocol
else if (packetSize == sPartInfoPC1) { // PC1 Packet
Udp.read(packetBuffer, 1347); // Read the Project Cars 1 protocol UDP packet, and put in it packetBuffer 1347
//udp1347(); // Witch output (i.e. LED's) is set, under what circumstances
}

else if (packetSize == sTelemetryPC1) { // PC1 Packet
Udp.read(packetBuffer,1367); // Read the Project Cars 1 protocol UDP packet, and put in it packetBuffer 1367
//Serial.println(" Packetbuffer 1367 recieved");
udp1367(); // Witch output (i.e. LED's) is set, under what circumstances
carflags();
carflagsout();
}

}

// Hardware Output when not race mode (race or replay)
if (idle == 1) { // PC1 prototol (idle is 1, means not racing)
cfLights = false;
cfEngineA = false;
cfEngineW = false;
cfPlim = false;
cfAbs = false;
cfHandB = false;
cfStab = false;
cfTrac = false;
FuelLevel = 50;
carflagsout();
}

else {
//Serial.println("ELSE GameState == 0");
//outputLed();
//TM1637();
}

outputLed();
TM1637(); // What TM1637 should do is in here..
//TM1638(); // What TM1638 should do is in here..
//countTM1638();
//output(); // Witch output (i.e. LED's) is set, under what circumstances
//flags(); // Reflect in game Flags

//Debug options
//serialDisplay(); // Output to Serial port
//lcddisplay(); // Output to LCD display
//gamestateLCD(); // Debug option for displaying gamestate LCD, (CPU speed demanding)
}

// END OF PROGRAM


0_pc.h


//============================================================================
//= 0_pc.h
//============================================================================

// Incoming UDP packet fields
unsigned int localPort = 5606; // Pcars UDP Port on all platforms
byte packetBuffer[1500]; // buffer to hold incoming packet

//============================================================================
// Project Cars 1 protocol
//============================================================================
unsigned int sPartInfoPC1 = 1347; // Is PartInfo packetsize
unsigned int sTelemetryPC1 = 1367; // Is Telemetry packetsize

//============================================================================
// Project Cars 2 protocol
//============================================================================
unsigned int sGameStateDataPC2 = 24; // Game State data Project Cars 2 protocol
unsigned int sRaceDataPC2 = 308; // Race data Project Cars 2 protocol
unsigned int sTelemetryPC2 = 559; // Telemetry Project Cars 2 protocol
unsigned int sTimeStatsDataPC2 = 1024; // Timing Stats data Project Cars 2 protocol
unsigned int sTimingsDataPC2 = 1063; // Participant Stats and records Project Cars 2 protocol
unsigned int sParticipantsStatsPC2 = 1040; // Participant Stats data Project Cars 2 protocol
unsigned int sParticipantsDataPC2 = 1136; // Participant Stats and records Project Cars 2 protocol
unsigned int sParticipantVehicleNamesDataPC2 = 1164; // Participant names data Project Cars 2 protocol
unsigned int sVehicleClassNamesDataPC2 = 1452; // Participant Vehicle names Project Cars 2 protocol

//bool inMenu = true;
bool inGame = false;
bool practiceStart = false;
bool raceStart = false;
byte raceLoading = 81;
bool needPartInfo = false;
bool needSetup = false;
bool firstRun = true;
bool ChequeredFlag = 0;

// booleans
// Carflags
bool cfLights = false; // Bit 0 Headlight
bool cfEngineA = false; // Bit 1 Engine Active / ON
bool cfEngineW = false; // Bit 2 Engine Warning
bool cfPlim = false; // Bit 3 Speed Limiter
bool cfAbs = false; // Bit 4 ABS
bool cfHandB = false; // Bit 5 Handbrake
bool cfStab = false; // Bit 6 ESP, Works with PC1 protocol, but probably doesnt work with PC2 protocol
bool cfTrac = false; // Bit 7 TCS, Works with PC1 protocol, doesnt work with PC2 protocol

// GameState
bool gSExited = false; // Bit 0 as BITs doesnt work, can use help on this one !
bool gSFrontEnd = false; // Bit 1 as BITs doesnt work, can use help on this one !
bool gSPlaying = false; // Bit 2 as BITs doesnt work, can use help on this one !
bool gSPaused = false; // Bit 3 as BITs doesnt work, can use help on this one !
// Bit 4 Does something, but what? , can use help on this one !
// Bit 5 Does something, but what? , can use help on this one !
// Bit 6 Does something, but what? , can use help on this one !

/*
// SessionState
bool sSInvalid = false; // Bit 0 as BITs doesnt work, can use help on this one !
bool sSPractise = false; // Bit 1 as BITs doesnt work, can use help on this one !
bool sSTest = false; // Bit 2 as BITs doesnt work, can use help on this one !
bool sSQualify = false; // Bit 3 as BITs doesnt work, can use help on this one !
bool sSFormationLap = false; // Bit 4 as BITs doesnt work, can use help on this one !
bool sSRace = false; // Bit 5 as BITs doesnt work, can use help on this one !
bool sSTimeAttack = false; // Bit 6 as BITs doesnt work, can use help on this one !
*/
// RaceState
bool rSInvalid = false; // Bit 0 as BITs doesnt work, can use help on this one !
bool rSNotStarted = false; // Bit 1 as BITs doesnt work, can use help on this one !
bool rSRacing = false; // Bit 2 as BITs doesnt work, can use help on this one !
bool rSFinished = false; // Bit 3 as BITs doesnt work, can use help on this one !
bool rSDisqualified = false; // Bit 4 as BITs doesnt work, can use help on this one !
bool rSRetired = false; // Bit 5 as BITs doesnt work, can use help on this one !
bool rSDNF = false; // Bit 6 as BITs doesnt work, can use help on this one !


unsigned int maxTemp = 105; // Max Engine Temperature / Overheating
unsigned int fuelLow = 10; // percentage when Fuel low led : goes ON
unsigned int fuelCrit = 5; // percentage when Fuel low led : goes FLASHING
byte idle = 0; // idle setting

unsigned long blinkStartMillis; // For Fuel Blink, some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long blinkPeriod = 500; // the value is a number of milliseconds

//============================================================================
//= Original data_out.h.h
//============================================================================
//============================================================================
//= Packetsize 1367
//============================================================================
byte GameState; // 3
byte UnfilteredThrottle; // 6
byte UnfilteredBrake; // 7
byte UnfilteredSteering; // 8
byte UnfilteredClutch; // 9
byte RaceState; // 10
byte LapsInEvent; // 11
float BestLapTime; // 12 - 15
float LastLapTime; // 16 - 19
float CurrentTime; // 20 - 23
float SplitTimeAhead; // 24
float SplitTimeBehind; // 28
float SplitTime; // 32
float EventTimeRemaining; // 36

float PersonalFastestLapTime; // 40
float WorldFastestLapTime; // 44
float CurrentSector1Time; // 48
float CurrentSector2Time; // 52
float CurrentSector3Time; // 56
float FastestSector1Time; // 60
float FastestSector2Time; // 64
float FastestSector3Time; // 68
float PersonalFastestSector1Time; // 72
float PersonalFastestSector2Time; // 76
float PersonalFastestSector3Time; // 80
float WorldFastestSector1Time; // 84
float WorldFastestSector2Time; // 88
float WorldFastestSector3Time; // 92
unsigned int JoyPad; // 96

byte HighestFlag; // 98
int OldHighestFlag; // Store Recent Flagsituation
byte PitModeSchedule; // 99


int OilTempCelsius; // 100
unsigned int OilPressureKPa; // 102, 103
int WaterTempCelsius; // 104, 105
unsigned int WaterPressureKPa; // 106, 107
unsigned int FuelPressureKPa; // 108, 109
byte CarFlags; // 110
byte FuelCapacity; // 111
byte Brake; // 112
byte Throttle; // 113
byte Clutch; // 114
char Steering; // 115
float FuelLevel; // 116 - 119
float Speed; // 120 - 123
unsigned int Rpm; // 124, 125 RPM 1
unsigned int MaxRpm; // 126, 127 MaxRPM 1
byte GearNumGears; // 128
byte currentGear;
byte maxGears;
byte BoostAmount; // 129
char EnforcedPitStopLap; // 130
byte CrashState; // 131
float OdometerKM; // 132 - 135
float Orientation[3]; // 136 - 138
float LocalVelocity[3]; // 148 - 150
float WorldVelocity[3]; // 160 - 162
float AngularVelocity[3]; // 172 - 174
float LocalAcceleration[3]; // 184 - 186
float WorldAcceleration[3]; // 196 - 198

float ExtentsCentre[3]; // 208 - 210
byte TyreFlags[4]; // 220 - 223
byte Terrain[4]; // 224 - 227
float TyreY[4]; // 228 - 231
float TyreRPS[4]; // 244 - 247
float TyreSlipSpeed[4]; // 260 - 263
byte TyreTemp[4]; // 276 - 279
byte TyreGrip[4]; // 280 - 283
float TyreHeightAboveGround[4]; // 284 - 287

float TyreLateralStiffness[4]; // 300 - 304
byte TyreWear[4]; // 316 - 319
byte BrakeDamage[4]; // 320 - 324
//byte SuspensionDamage[4]; // 324 - 328
byte SuspensionDamageFL;
byte SuspensionDamageFR;
byte SuspensionDamageRL;
byte SuspensionDamageRR;
int BrakeTempCelsius[4]; // 328
unsigned int TyreTreadTemp[4]; // 336
unsigned int TyreLayerTemp[4]; // 344
unsigned int TyreCarcassTemp[4]; // 352
unsigned int TyreRimTemp[4]; // 360
unsigned int TyreInternalAirTemp[4]; // 368
float WheelLocalPositionY[4]; // 376 - 379
float RideHeight[4]; // 392 - 396

float SuspensionTravel[4]; // 408 - 412
unsigned int AirPressure[4]; // 440 - 443
float SuspensionVelocity[4]; // 424 - 427
float EngineSpeed; // 448 - 451
float EngineTorque; // 452 - 455
byte AeroDamage; // 456
byte EngineDamage; // 457
char AmbientTemperature; // 458
char TrackTemperature; // 459
byte RainDensity; // 460
char WindSpeed; // 461
char WindDirectionX; // 462
char WindDirectionY; // 463

byte DPad; // 1366

//============================================================================
//= Packetsize 1347
//============================================================================
char sCarName[64];

char sCarClassName[64];
char sTrackLocation[64];
char sTrackVariation[64];
char sName[16]; //char sName[16][64]; // 259
float sFastestLapTime[16];

//============================================================================
//= Led Test / Hardware Check
//============================================================================

void ledTest() {
mcp1.digitalWrite(mcp1ledpinLight, HIGH);
mcp1.digitalWrite(mcp1ledpinABS, HIGH);
mcp1.digitalWrite(mcp1ledpinTCS, HIGH);
mcp1.digitalWrite(mcp1ledpinESP, HIGH);
mcp1.digitalWrite(mcp1ledpinOilTemp, HIGH);
mcp1.digitalWrite(mcp1ledpinPit, HIGH);
mcp1.digitalWrite(mcp1ledpinFuel, HIGH);
mcp1.digitalWrite(mcp1ledpinWiFi, HIGH);
digitalWrite(ledpinWiFi, HIGH);

// RGB Led
mcp1.digitalWrite(mcp1ledpinRGBB, HIGH); //Turn on ALL RGB LED's = white
mcp1.digitalWrite(mcp1ledpinRGBG, HIGH);
mcp1.digitalWrite(mcp1ledpinRGBR, HIGH);

delay(3000);

mcp1.digitalWrite(mcp1ledpinLight, LOW);
mcp1.digitalWrite(mcp1ledpinABS, LOW);
mcp1.digitalWrite(mcp1ledpinTCS, LOW);
mcp1.digitalWrite(mcp1ledpinESP, LOW);
mcp1.digitalWrite(mcp1ledpinOilTemp, LOW);
mcp1.digitalWrite(mcp1ledpinPit, LOW);
mcp1.digitalWrite(mcp1ledpinFuel, LOW);

// RGB Led
mcp1.digitalWrite(mcp1ledpinRGBB, LOW); //Turn off ALL RGB LED's
mcp1.digitalWrite(mcp1ledpinRGBG, LOW);
mcp1.digitalWrite(mcp1ledpinRGBR, LOW);
mcp1.digitalWrite(mcp1ledpinWiFi, LOW);
digitalWrite(ledpinWiFi, LOW);

}


2L_0_pc.h


//============================================================================
//= void_Outputs.h
//============================================================================

//============================================================================
//= UDP Project Cars 2
//============================================================================
void udp559() {
CarFlags = (packetBuffer[17]);
OilTempCelsius = (packetBuffer[18]); // Oil Temp (Celsius) WORKS
GearNumGears = (packetBuffer[45]);
Rpm = word((packetBuffer[41]), (packetBuffer[40]));
MaxRpm = word((packetBuffer[43]), (packetBuffer[42]));
FuelCapacity = (packetBuffer[28]); // Fuel Capacity WORKS
FuelLevel = 50; // Dummy value as long as the FuelLevel isn't working BUG? help appreciated
}

void udp24() {
GameState = (packetBuffer[15]);
//gamestate();
if (GameState == 0) idle = true; else idle = false;
}

void udp1136() {
RaceState = (packetBuffer[20]);
//racestate();
}


//============================================================================
//= UDP Project Cars 1
//============================================================================
void udp1367() {

// Works, Currently not used:
//PitModeSchedule = packetBuffer[99]; // byte PitModeSchedule; // 99 - 29
//OilPressureKPa = packetBuffer[102]; // unsigned int // OilPress 1st // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
//WaterPressureKPa = packetBuffer[106]; // unsigned int WaterPressureKPa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
//FuelPressureKPa = packetBuffer[108]; // unsigned int FuelPressureKPa; // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
//WaterTempCelsius = packetBuffer[104]; // int WaterTempCelsius; // (Celsius)
//AeroDamage = ((packetBuffer[456]) / 2.55); // Byte // AeroDamage // [ RANGE = 0.0f->1.0f ]
//EngineDamage = ((packetBuffer[457]) / 2.55); // Byte // EngineDamage // [ RANGE = 0.0f->1.0f ]
//CrashState = packetBuffer[131]; // Byte // CrashState
//BrakeDamage = ((packetBuffer[320]) / 2.55); // Byte // byte BrakeDamage[4];
//SuspensionDamageFL = ((packetBuffer[324]) / 2.55); // Byte // byte SuspensionDamage[4]; Front LEft
//SuspensionDamageFR = ((packetBuffer[325]) / 2.55); // Byte // byte SuspensionDamage[4]; Front Right
//SuspensionDamageRL = ((packetBuffer[326]) / 2.55); // Byte // byte SuspensionDamage[4]; Rear Left
//SuspensionDamageRR = ((packetBuffer[327]) / 2.55); // Byte // byte SuspensionDamage[4]; Rear Left

GameState = packetBuffer[3];
gamestate();
if (GameState == 1) idle = true; else idle = false;

RaceState = packetBuffer[10];
racestate();

CarFlags = packetBuffer[110];
OilTempCelsius = packetBuffer[100]; // Oil Temp (Celsius) WORKS
GearNumGears = packetBuffer[128]; // Actual Gear
Rpm = word((packetBuffer[125]), (packetBuffer[124]));
MaxRpm = word((packetBuffer[127]), (packetBuffer[126]));
FuelCapacity = packetBuffer[111]; // Fuel Capacity WORKS


uint32_t FL=0;
for (uint8_t i=119; i>115; i--) {
FL=FL<<8;
FL=FL+packetBuffer[i];
}

memcpy(&FuelLevel, &FL, 4);
FuelLevel = FuelLevel * FuelCapacity;

// Speed (KMh)
uint32_t SP=0;
for (uint8_t i=123; i>119; i--) {
SP=SP<<8;
SP=SP+packetBuffer[i];
}
memcpy(&Speed, &SP, 4);
Speed = Speed * 3.6; // To get m/s to KMh

}

void udp1347() {
// put code here
}


2L_2_flags.h


//============================================================================
//= Flag colours
//============================================================================
void greenFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, LOW); //Turn on green LED
mcp1.digitalWrite(mcp1ledpinRGBG, HIGH);
mcp1.digitalWrite(mcp1ledpinRGBR, LOW);
}

void yellowFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, LOW); //Turn on red and green LED = yellow
mcp1.digitalWrite(mcp1ledpinRGBG, HIGH);
mcp1.digitalWrite(mcp1ledpinRGBR, HIGH);
}

void doubleyellowFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, LOW); //Turn on red and green LED = yellow
mcp1.digitalWrite(mcp1ledpinRGBG, HIGH);
mcp1.digitalWrite(mcp1ledpinRGBR, HIGH);
}

void blueFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, HIGH); //Turn on blue LED
mcp1.digitalWrite(mcp1ledpinRGBG, LOW);
mcp1.digitalWrite(mcp1ledpinRGBR, LOW);
}

void redFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, LOW);
mcp1.digitalWrite(mcp1ledpinRGBG, LOW);
mcp1.digitalWrite(mcp1ledpinRGBR, HIGH); //Turn on red LED
}

void whiteFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, HIGH); //Turn on ALL LED = white
mcp1.digitalWrite(mcp1ledpinRGBG, HIGH);
mcp1.digitalWrite(mcp1ledpinRGBR, HIGH);
}

void noFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, LOW); //Turn on ALL LED = white
mcp1.digitalWrite(mcp1ledpinRGBG, LOW);
mcp1.digitalWrite(mcp1ledpinRGBR, LOW);
}

void unsportmanFlag() {
mcp1.digitalWrite(mcp1ledpinRGBB, HIGH); //Turn on blue and green LED = mint
mcp1.digitalWrite(mcp1ledpinRGBG, HIGH);
mcp1.digitalWrite(mcp1ledpinRGBR, LOW);
}

void flags() {
HighestFlag = (packetBuffer[98]); // Read actual flag

if (HighestFlag != OldHighestFlag) // Only do stuff if HighestFlag has changed

{
lcd1.init();
lcd1.backlight();
lcd1.clear();
lcd1.setCursor(0, 0); lcd1.print("Current flag:");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);

if (HighestFlag == 1)
{
//Serial.println("Green flag, go go go!");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);
lcd1.setCursor(0, 1); lcd1.print("Green flag");
greenFlag();
ChequeredFlag = 0;
}

else if (HighestFlag == 2)
{
//Serial.println("Blue flag, blue flag!");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);
lcd1.setCursor(0, 1); lcd1.print("Blue flag");
blueFlag();
}

else if (HighestFlag == 3)
{
//Serial.println("White flag, slow car in area, watch out");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);
lcd1.setCursor(0, 1); lcd1.print("White flag");
whiteFlag();
}

else if (HighestFlag == 4)
{
//Serial.println("Final lap, c'mon push!");
whiteFlag();
}

else if (HighestFlag == 5)
{
//Serial.println("Red flag! Huge pileup ahead.");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);
lcd1.setCursor(0, 1); lcd1.print("Red flag");
redFlag();
}

else if (HighestFlag == 6)
{
//Serial.println("Yellow flag, slow down");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);
lcd1.setCursor(0, 1); lcd1.print("Yellow flag");
yellowFlag();
}

else if (HighestFlag == 7)
{
//Serial.println("Double yellow, watch out");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);
lcd1.setCursor(0, 1); lcd1.print("DYellow flag");
doubleyellowFlag();
}

else if (HighestFlag == 8)
{
//Serial.println("Black and white flag, unsportsmanlike conduct");
lcd1.setCursor(15, 0); lcd1.print(HighestFlag);
lcd1.setCursor(0, 1); lcd1.print("B & W flag");
unsportmanFlag();
}

else if (HighestFlag == 9)
{
//Serial.println("Black and orange, mechanical failure");
lcd1.setCursor(0, 0); lcd1.print("Mech. Failure");
lcd1.setCursor(0, 1); lcd1.print("B & O flag");
// No Flag configured yet
}

else if (HighestFlag == 10)
{
//Serial.println("Black flag, disqualified!");
lcd1.setCursor(0, 0); lcd1.print("Disqualified");
lcd1.setCursor(0, 1); lcd1.print("Black flag");
// No Flag configured yet
}
}

else if (HighestFlag == 11)
{
//Serial.println("Chequered flag!");
lcd1.setCursor(0, 0); lcd1.print("Finish");
lcd1.setCursor(0, 1); lcd1.print("Chequered flag!");
if (ChequeredFlag == 0)
{
noFlag();
delay(250);
whiteFlag();
delay(250);
noFlag();
delay(250);
whiteFlag();
delay(250);
noFlag();

ChequeredFlag = 1;
}
}
OldHighestFlag = HighestFlag; // Store current value in OldHighestFlag so we can see if it has changed later

/*
// If not in race, turn off RGB led
//if ((uDP.ParticipantInfo[uDP.ViewedParticipantIndex, 12]) != 2)
//{
noFlag();
//}
*/
}


2L_debug.h


//============================================================================
//= Serial Section - Debug option for displaying Gamestates / debugging
//============================================================================
void serialDisplay() {
Serial.println("");
Serial.println("************************************************************");
Serial.print("Engine Temp : "); Serial.print(OilTempCelsius); Serial.println(" C"); // also check to see if UDP Works
//Serial.print("EngineTorque : "); Serial.print(EngineTorque); Serial.println(" hp? / Nm?");
//Serial.print("Speed : "); Serial.print(Speed); Serial.println(" KMh");
//Serial.print("EngineSpeed : "); Serial.println(EngineSpeed); // Serial.println(" ???");
//Serial.print("FuelLevel : "); Serial.print(FuelLevel); Serial.print("/"); Serial.print(FuelCapacity); Serial.println(" L");
//Serial.print("CarFlags : "); Serial.println(CarFlags, BIN);
//Serial.print("OilPressureKPa1 : "); Serial.print(OilPressureKPa1); Serial.println(" Kpa");
//Serial.print("WaterPressureKPa1 : "); Serial.print(WaterPressureKPa1); Serial.println(" Kpa");
//Serial.print("FuelPressureKPa1 : "); Serial.print(FuelPressureKPa1); Serial.println(" Kpa");
//Serial.print("Packetbuffer 458 : "); Serial.print(packetBuffer[458]); Serial.println(" Ambient Temperature");
//Serial.print("Packetbuffer 459 : "); Serial.print(packetBuffer[459]); Serial.println(" Track Temperature");
//Serial.print("RPM : "); Serial.print(Rpm); Serial.print(" / "); Serial.print(MaxRpm); Serial.println(" RPM");
//Serial.print("PitModeSchedule : "); Serial.println(PitModeSchedule);
//Serial.print("AeroDamage : "); Serial.println(AeroDamage);
//Serial.print("EngineDamage : "); Serial.println(EngineDamage);
//Serial.print("CrashState : "); Serial.println(CrashState);
//Serial.print("BrakeDamage : "); Serial.println(BrakeDamage);
//Serial.print("SuspensionDamage FL : "); Serial.println(SuspensionDamageFL);
//Serial.print("SuspensionDamage FR : "); Serial.println(SuspensionDamageFR);
//Serial.print("SuspensionDamage RL : "); Serial.println(SuspensionDamageRL);
//Serial.print("SuspensionDamage RR : "); Serial.println(SuspensionDamageRR);
//Serial.print("Uf Steering : "); Serial.println(UnfilteredSteering);
//Serial.print("Light : "); Serial.println(cfLights);
//Serial.print("GameState : "); Serial.println(GameState);
//Serial.print("GameState BIN : "); Serial.println(GameState, BIN);
//Serial.print("idle : "); Serial.println(idle);

//Serial.println("---------------------------");
//Serial.print("GameState gSExited : "); Serial.println(gSExited);
//Serial.print("GameState gSFrontEnd : "); Serial.println(gSFrontEnd);
//Serial.print("GameState gSPlaying : "); Serial.println(gSPlaying);
//Serial.print("GameState gSPaused : "); Serial.println(gSPaused);
//Serial.println("---------------------------");
//Serial.print("RaceState : "); Serial.println(RaceState);
//Serial.print("RameState BIN : "); Serial.println(RaceState, BIN);
//Serial.println("---------------------------");
//Serial.print("RaceState rSInvalid : "); Serial.println(rSInvalid);
//Serial.print("RaceState rSNotStarted : "); Serial.println(rSNotStarted);
//Serial.print("RaceState rSRacing : "); Serial.println(rSRacing);
//Serial.print("RaceState rSFinished : "); Serial.println(rSFinished);
//Serial.print("RaceState rSDisqualified : "); Serial.println(rSDisqualified);
//Serial.print("RaceState rSRetired : "); Serial.println(rSRetired);
//Serial.print("RaceState rSDNF : "); Serial.println(rSDNF);
//Serial.println("---------------------------");

delay (500); // For refreshing to quickly on serial, but this delays whole sketch
}

//============================================================================
//= LCD Section - Debug option for displaying Gamestates / debugging
//============================================================================
void gamestateLCD() {
lcd1.backlight(); // Turn LCD Backlight on
// 1st Line
lcd1.setCursor(0, 0); lcd1.print("IG:"); lcd1.setCursor(3, 0); lcd1.print(inGame); // inGame - IG
lcd1.setCursor(6, 0); lcd1.print("PS:"); lcd1.setCursor(9, 0); lcd1.print(practiceStart);// practiceStart = PS
lcd1.setCursor(12, 0); lcd1.print("RS:"); lcd1.setCursor(15, 0); lcd1.print(raceStart); // racestart = RS

// 2nd Line
lcd1.setCursor(0, 1); lcd1.print("NS:"); lcd1.setCursor(3, 1); lcd1.print(needSetup); // needSetup
lcd1.setCursor(6, 1); lcd1.print("NP:"); lcd1.setCursor(9, 1); lcd1.print(needPartInfo); // needPartInfo = NP
lcd1.setCursor(12, 1); lcd1.print("FR:"); lcd1.setCursor(15, 1); lcd1.print(firstRun); // firstRun = FR
}

//============================================================================
//= LCD Race options display
//============================================================================
void lcddisplay() {
// lcd1.init();
lcd1.backlight();
// lcd1.clear();
// 1st Line
lcd1.setCursor(0, 0); lcd1.print("Fuel:"); lcd1.setCursor( 5, 0); lcd1.print(FuelLevel);
lcd1.setCursor(8, 0); lcd1.print("Temp:"); lcd1.setCursor(13, 0); lcd1.print(OilTempCelsius);
// 2nd Line
lcd1.setCursor(0, 1); lcd1.print("Spd:"); lcd1.setCursor( 4, 1); lcd1.print(Speed);
lcd1.setCursor(9, 1); lcd1.print("Gear:"); lcd1.setCursor(15, 1); lcd1.print(GearNumGears);

//lcd1.setCursor(1, 0); lcd1.print(Rpm); lcd1.setCursor( 6, 0); lcd1.print("/"); lcd1.setCursor(8, 0); lcd1.print(MaxRpm); lcd1.setCursor( 12, 0); lcd1.print(" Rpm");
}


2L_out.h


void fuelBlink() // function to blink an LED if the blink period has ended
{
if (currentMillis - blinkStartMillis >= blinkPeriod) // test whether the period has elapsed
{
mcp1.digitalWrite(mcp1ledpinFuel, !mcp1.digitalRead(mcp1ledpinFuel)); // Flash FuelLED
blinkStartMillis = currentMillis; // IMPORTANT to save the start time of the current LED state.
}
}

void carflags(){
if (bitRead(CarFlags, 0)) cfLights = true; else cfLights = false;
if (bitRead(CarFlags, 1)) cfEngineA = true; else cfEngineA = false;
if (bitRead(CarFlags, 2)) cfEngineW = true; else cfEngineW = false;
if (bitRead(CarFlags, 3)) cfPlim = true; else cfPlim = false;
if (bitRead(CarFlags, 4)) cfAbs = true; else cfAbs = false;
if (bitRead(CarFlags, 5)) cfHandB = true; else cfHandB = false;
if (bitRead(CarFlags, 6)) cfStab = true; else cfStab = false;
if (bitRead(CarFlags, 7)) cfTrac = true; else cfTrac = false;
}

void carflagsout(){
// Lights
if (cfLights == true) {
// Serial.println("Light ON"); delay(100); // Debug option delay is for MCP
mcp1.digitalWrite(mcp1ledpinLight, HIGH); // turn Light LED on
}
else {
// Serial.println("Light OFF"); delay(100); // Debug option delay is for MCP
mcp1.digitalWrite(mcp1ledpinLight, LOW); // turn Light LED off
}

// in Pit Lane
if (cfPlim == true) {
// Serial.println("Speed Limited"); // Debug option
//mcp1.digitalWrite(mcp1ledpinPit, HIGH); // turn Pit Limiter LED on / in the Pitlane
//module1.setLED(HIGH, 1);
}
else {
// Serial.println("Speed NOT Limited"); // Debug option
//mcp1.digitalWrite(mcp1ledpinPit, LOW); // turn Pit Limiter LED off / NOT in the Pitlane
//module1.setLED(LOW, 1);
}

// ABS
if (cfAbs == true) {
// Serial.println("ABS ON"); // Debug option
mcp1.digitalWrite(mcp1ledpinABS, HIGH); // turn ABS LED on
}
else {
// Serial.println("ABS OFF"); // Debug option
mcp1.digitalWrite(mcp1ledpinABS, LOW); // turn ABS LED off
}

// ESP
if (cfStab == true) {
// Serial.println("ESP ON"); // Debug option
mcp1.digitalWrite(mcp1ledpinESP, HIGH); // turn ESP LED on
}
else {
// Serial.println("ESP OFF"); // Debug option
mcp1.digitalWrite(mcp1ledpinESP, LOW); // turn ESP LED off
}

// TCS
if (cfTrac == true) {
// Serial.println("TCS ON"); // Debug option
mcp1.digitalWrite(mcp1ledpinTCS, HIGH); // turn TCS LED on
}
else {
// Serial.println("TCS OFF"); // Debug option
mcp1.digitalWrite(mcp1ledpinTCS, LOW); // turn TCS LED off
}


}

void gamestate(){
if (bitRead(GameState, 0)) gSExited = true; else gSExited = false;
if (bitRead(GameState, 1)) gSFrontEnd = true; else gSFrontEnd = false;
if (bitRead(GameState, 2)) gSPlaying = true; else gSPlaying = false;
if (bitRead(GameState, 3)) gSPaused = true; else gSPaused = false;
}

void racestate(){
if (bitRead(RaceState, 0)) rSInvalid = true; else rSInvalid = false;
if (bitRead(RaceState, 1)) rSNotStarted = true; else rSNotStarted = false;
if (bitRead(RaceState, 2)) rSRacing = true; else rSRacing = false;
if (bitRead(RaceState, 3)) rSFinished = true; else rSFinished = false;
if (bitRead(RaceState, 4)) rSDisqualified = true; else rSDisqualified = false;
if (bitRead(RaceState, 5)) rSRetired = true; else rSRetired = false;
if (bitRead(RaceState, 6)) rSDNF = true; else rSDNF = false;
}

void outputLed(){
// Lights
if (cfLights == true) {
// Serial.println("Light ON"); delay(100); // Debug option delay is for MCP
mcp1.digitalWrite(mcp1ledpinLight, HIGH); // turn Light LED on
}
else {
// Serial.println("Light OFF"); delay(100); // Debug option delay is for MCP
mcp1.digitalWrite(mcp1ledpinLight, LOW); // turn Light LED off
}

// in Pit Lane
if (cfPlim == true) {
// Serial.println("Speed Limited"); // Debug option
//mcp1.digitalWrite(mcp1ledpinPit, HIGH); // turn Pit Limiter LED on / in the Pitlane
//module1.setLED(HIGH, 1);
}
else {
// Serial.println("Speed NOT Limited"); // Debug option
//mcp1.digitalWrite(mcp1ledpinPit, LOW); // turn Pit Limiter LED off / NOT in the Pitlane
//module1.setLED(LOW, 1);
}

// ABS
if (cfAbs == true) {
// Serial.println("ABS ON"); // Debug option
mcp1.digitalWrite(mcp1ledpinABS, HIGH); // turn ABS LED on
}
else {
// Serial.println("ABS OFF"); // Debug option
mcp1.digitalWrite(mcp1ledpinABS, LOW); // turn ABS LED off
}

// ESP
if (cfStab == true) {
// Serial.println("ESP ON"); // Debug option
mcp1.digitalWrite(mcp1ledpinESP, HIGH); // turn ESP LED on
}
else {
// Serial.println("ESP OFF"); // Debug option
mcp1.digitalWrite(mcp1ledpinESP, LOW); // turn ESP LED off
}

// TCS
if (cfTrac == true) {
// Serial.println("TCS ON"); // Debug option
mcp1.digitalWrite(mcp1ledpinTCS, HIGH); // turn TCS LED on
}
else {
// Serial.println("TCS OFF"); // Debug option
mcp1.digitalWrite(mcp1ledpinTCS, LOW); // turn TCS LED off
}

/*
if (bitRead(SessionState, 0)) sSInvalid = true; else sSInvalid = false;
if (bitRead(SessionState, 1)) sSPractise = true; else sSPractise = false;
if (bitRead(SessionState, 2)) sSTest = true; else sSTest = false;
if (bitRead(SessionState, 3)) sSQualify = true; else sSQualify = false;
if (bitRead(SessionState, 4)) sSFormationLap = true; else sSFormationLap = false;
if (bitRead(SessionState, 5)) sSRace = true; else sSRace = false;
if (bitRead(SessionState, 6)) sSTimeAttack = true; else sSTimeAttack = false;
*/

if (OilTempCelsius >= maxTemp) { // When Temp is Equal or Greater than maxTemp
// Serial.print("Engine Temp to High, above :"); Serial.println(maxTemp); // Debug option
mcp1.digitalWrite(mcp1ledpinOilTemp, HIGH); // turn Engine Temp LED on
}
else {
// Serial.print("Engine Temp OK below :"); Serial.println(maxTemp); // Debug option
mcp1.digitalWrite(mcp1ledpinOilTemp, LOW); // turn Engine Temp LED off
}

// Gear
currentGear = GearNumGears & 0xf; // & GearNumGears with 00001111(15) to get value of Low4 bits
maxGears = GearNumGears >> 4; // Shift GearNumGears 4 bits Right. Shift out low

// Fuel
if (FuelLevel <= (( FuelCapacity * fuelCrit) / 100)) {
//Serial.print("Fuel level is below Critical "); Serial.print(fuelCrit); Serial.println(" %"); // Debug option
currentMillis = millis(); // get the current "time"
fuelBlink();
}

else if (FuelLevel <= (( FuelCapacity * fuelLow) / 100)) {
//Serial.print("Fuel level is BELOW "); Serial.print(fuelLow); Serial.println(" %"); // Debug option
mcp1.digitalWrite(mcp1ledpinFuel, HIGH); // turn FuelLED on

}

else {
//Serial.print("Fuel level is ABOVE "); Serial.print(fuelCrit); Serial.print (" and "); // Debug option
//Serial.print(fuelLow); Serial.println(" %");
mcp1.digitalWrite(mcp1ledpinFuel, LOW); // turn FuelLED off
}

}


//============================================================================
//= TM1637 module('s)
//============================================================================

//============================================================================
//= tm1637-1 D10 Pin:19, CLK Pin:18
//============================================================================

#include <TM1637Display.h>
const int CLKpin = 18; // GPIO 18 on ESP32 for TM1638 CLOCK
const int DIOpin = 19; // GPIO 19 on ESP32 for TM1638 DATA
TM1637Display module1637_1(CLKpin, DIOpin); // define a module #1 on DATA pin 19, CLOCK pin 18 and STROBE pin 5

void TM1637(){

module1637_1.showNumberDec(OilTempCelsius); // Display Oil / Engine Temperature

}

//============================================================================
//= TM1638 module('s)
//============================================================================

//============================================================================
//= tm1638-1 D10 Pin:19, CLK Pin:18, STB Pin: 5
//= tm1638-2 D10 Pin:19, CLK Pin:18, STB Pin:15
//============================================================================
/*
#include <TM1638.h>
const int STB1pin = 5; // GPIO 5 on ESP32 for TM1638-1 STROBE
const int STB2pin = 15; // GPIO 15 on ESP32 for TM1638-2 STROBE
const int CLKpin = 18; // GPIO 18 on ESP32 for TM1638 CLOCK
const int Dpin = 19; // GPIO 19 on ESP32 for TM1638 DATA
TM1638 module1638_1(Dpin, CLKpin, STB1pin); // define a module #1 on DATA pin 19, CLOCK pin 18 and STROBE pin 5
TM1638 module1638_2(Dpin, CLKpin, STB2pin); // define a module #1 on DATA pin 19, CLOCK pin 18 and STROBE pin 15
//byte butTM1638;

void TM1638(){
// butTM1638 = module1.getButtons(); // Cable Broken?
module1638_1.setDisplayToDecNumber(OilTempCelsius,0,false); // Display Oil / Engine Temperature
module1638_2.setDisplayToDecNumber(Rpm,0,false); // Display RPM

// module1638_1.setDisplayToDecNumber(FuelLevel,0,false); // Display FuelLevel
// module1638_1.setDisplayToDecNumber(Speed,0,false); // Display Speed
// module1638_1.setLEDs(0x0000); // Turn single Leds off
// module1638_1.setDisplayToDecNumber(butTM1638,0,false); // To test if buttons work
*/

/*
if (butTM1638==1) {
Serial.println("butTM1638 = 1");
module1638_1.setLED(HIGH, 0);
delay(100);
}

if (butTM1638==4) {
Serial.println("butTM1638 = 4");
module1638_1.setLED(HIGH, 1);
delay(100);
}

if (butTM1638==8) {
Serial.println("butTM1638 = 8");
module1638_1.setLED(HIGH, 2);
delay(100);
}

}
*/


info


/*
GPIO 1 UART 0 TX (serial)
GPIO 2 WiFi Connected (Onboard Led)
GPIO 3 UART 0 RX (serial)
GPIO 4
GPIO 5 TM 1638-1 STB
GPIO 12
GPIO 13
GPIO 14
GPIO 15 TM 1638-2 STB
GPIO 16 UART 2 RX
GPIO 17 UART 2 TX
GPIO 18 TM 1638 CLK
GPIO 19 TM 1638 D10
GPIO 21 i2c SDA 2 LCD Display & MCP (Power and ground from pin VIN and GND)
GPIO 22 i2c SCL 2 LCD Display & MCP (Power and ground from pin VIN and GND)
GPIO 23
GPIO 25
GPIO 26
GPIO 27
GPIO 32
GPIO 33

GPI 34 Input only
GPI 35 Input only
GPI 36 Input only
GPI 37 Input only
GPI 38 Input only
GPI 39 Input only

MCP 1
GPA0 - WiFi Connected
GPA1 - LED ABS
GPA2 - LED ESP
GPA3 - LED TCS
GPA4 - LED Light
GPA5 - LED Oil / Engine Temperature
GPA6 - LED Pit(limiter)
GPA7 - LED Fuel (be)LOW
GPB0 - LED RGB Flag - Red
GPB1 - LED RGB Flag - Green
GPB2 - LED RGB Flag - Blue
GPB3 -
GPB4 -
GPB5 -
GPB6 -
GPB7 -

http://forum.projectcarsgame.com/showthread.php?43111-How-to-import-data-from-wifi-into-arduino&highlight=Esp8266 Post 15
*/



void_PC2.h


//============================================================================
//= void_PC2.h
//============================================================================
/*
(
// Packetsize 1367
Packetnum = (packetBuffer[2]); // Byte // PacketNo
GameState = (packetBuffer[3]); // Byte // GameState
UnfilteredThrottle = (packetBuffer[6]); // Byte +// byte UnfilteredThrottle; // [ RANGE = 0->255 ]
UnfilteredBrake = (packetBuffer[7]); // Byte +// byte UnfilteredBrake; // [ RANGE = 0->255 ]
UnfilteredSteering = (packetBuffer[8]); // Byte +// byte UnfilteredSteering; // [ RANGE = 0->255 ]
UnfilteredClutch = (packetBuffer[9]); // Byte +// byte UnfilteredClutch; // [ RANGE = 0->255 ]
RaceState = (packetBuffer[10]); // Byte +// RaceState
LapsInEvent = (packetBuffer[11]); // Byte -// Laps In Event
bTime1 = (packetBuffer[12]); // float // BestLapTime 1st
bTime2 = (packetBuffer[13]); // float // BestLapTime 2nd
bTime3 = (packetBuffer[14]); // float // BestLapTime 3rd
bTime4 = (packetBuffer[15]); // float // BestLapTime 4th
lTime1 = (packetBuffer[16]); // float // LastLapTime 1st
lTime2 = (packetBuffer[17]); // float // LastLapTime 2nd
lTime3 = (packetBuffer[18]); // float // LastLapTime 3rd
lTime4 = (packetBuffer[19]); // float // LastLapTime 4th
cTime1 = (packetBuffer[20]); // float // CurrentTime 1st
cTime2 = (packetBuffer[21]); // float // CurrentTime 2nd
cTime3 = (packetBuffer[22]); // float // CurrentTime 3rd
cTime4 = (packetBuffer[23]); // float // CurrentTime 4th

SplitTimeAhead = (packetBuffer[24]); // float SplitTimeAhead; // 24
SplitTimeBehind = (packetBuffer[28]); // float SplitTimeBehind; // 28
SplitTime = (packetBuffer[32]); // float SplitTime; // 32
EventTimeRemaining = (packetBuffer[36]); // float EventTimeRemaining; // 36
PersonalFastestLapTime = (packetBuffer[40]); // float PersonalFastestLapTime; // 40
WorldFastestLapTime = (packetBuffer[44]); // float WorldFastestLapTime; // 44
CurrentSector1Time = (packetBuffer[48]); // float CurrentSector1Time; // 48
CurrentSector2Time = (packetBuffer[52]); // float CurrentSector2Time; // 52
CurrentSector3Time = (packetBuffer[56]); // float CurrentSector3Time; // 56
FastestSector1Time = (packetBuffer[60]); // float FastestSector1Time; // 60
FastestSector2Time = (packetBuffer[64]); // float FastestSector2Time; // 64
FastestSector3Time = (packetBuffer[68]); // float FastestSector3Time; // 68
PersonalFastestSector1Time = (packetBuffer[72]); // float PersonalFastestSector1Time; // 72
PersonalFastestSector2Time = (packetBuffer[76]); // float PersonalFastestSector2Time; // 76
PersonalFastestSector3Time = (packetBuffer[80]); // float PersonalFastestSector3Time; // 80
WorldFastestSector1Time = (packetBuffer[84]); // float WorldFastestSector1Time; // 84
WorldFastestSector2Time = (packetBuffer[88]); // float WorldFastestSector2Time; // 88
WorldFastestSector3Time = (packetBuffer[92]); // float WorldFastestSector3Time; // 92

JoyPad = (packetBuffer[96]); // unsigned int // unsigned int JoyPad;
HighestFlag = (packetBuffer[98]); // Byte +// Read actual flag
PitModeSchedule = (packetBuffer[99]); // Byte +// byte PitModeSchedule;// 16 is Pit requested

// 100
OilTempCelsius1 = (packetBuffer[100]); // int +// OilTemp 1st // [ UNITS = Celsius ] [ UNSET = 0.0f ]
OilTempCelsius2 = (packetBuffer[101]); // int // OilTemp 2nd // [ UNITS = Celsius ] [ UNSET = 0.0f ]
OilPressureKPa1 = (packetBuffer[102]); // unsigned int +// OilPress 1st // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
OilPressureKPa2 = (packetBuffer[103]); // unsigned int // OilPress 2nd // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
WaterTempCelsius1 = (packetBuffer[104]); // int +// WaterTemp 1st // [ UNITS = Celsius ] [ UNSET = 0.0f ]
WaterTempCelsius2 = (packetBuffer[105]); // int // Watertemp 2nd // [ UNITS = Celsius ] [ UNSET = 0.0f ]
WaterPressureKPa1 = (packetBuffer[106]); // unsigned int +// WaterPress 1st // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
WaterPressureKPa2 = (packetBuffer[107]); // unsigned int // WaterPress 2nd // [ UNITS = Kilopascal ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
FuelPressureKPa1 = (packetBuffer[108]); // unsigned int +// FuelPress 1st
FuelPressureKPa1 = (packetBuffer[109]); // unsigned int // FuelPress 2nd
CarFlags = (packetBuffer[110]); // Byte +// CarFlags
FuelCapacity = (packetBuffer[111]); // Byte +// FuelCapacity
cBrake = (packetBuffer[112]); // float/byte? // Brake // [ RANGE = 0.0f->1.0f ]
cThrottle = (packetBuffer[113]); // float/byte? // Throttle // [ RANGE = 0.0f->1.0f ]
cClutch = (packetBuffer[114]); // float/byte? // Clutch // [ RANGE = 0.0f->1.0f ]
cSteering = (packetBuffer[115]); // float/char? // Steering // [ RANGE = -1.0f->1.0f ]
FuelLevel1 = (packetBuffer[116]); // float // FuelLevel 1st // [ RANGE = 0.0f->1.0f ]
FuelLevel2 = (packetBuffer[117]); // float // FuelLevel 2nd // [ RANGE = 0.0f->1.0f ]
FuelLevel3 = (packetBuffer[118]); // float // FuelLevel 3rd // [ RANGE = 0.0f->1.0f ]
FuelLevel4 = (packetBuffer[119]); // float // FuelLevel 4th // [ RANGE = 0.0f->1.0f ]
Speed1 = (packetBuffer[120]); // float // Speed 1st // [ UNITS = Metres per-second ] [ RANGE = 0.0f->... ]
Speed2 = (packetBuffer[121]); // float // Speed 2nd // [ UNITS = Metres per-second ] [ RANGE = 0.0f->... ]
Speed3 = (packetBuffer[122]); // float // Speed 3rd // [ UNITS = Metres per-second ] [ RANGE = 0.0f->... ]
Speed4 = (packetBuffer[123]); // float // Speed 4th // [ UNITS = Metres per-second ] [ RANGE = 0.0f->... ]
Rpm1 = (packetBuffer[124]); // unsigned int +// Rpm 1st // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
Rpm2 = (packetBuffer[125]); // unsigned int +// Rpm 2nd // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
maxRpm1 = (packetBuffer[126]); // unsigned int +// MaxRpm 1st // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
maxRpm2 = (packetBuffer[127]); // unsigned int +// MaxRpm 2nd // [ UNITS = Revolutions per minute ] [ RANGE = 0.0f->... ] [ UNSET = 0.0f ]
GearNumGears = (packetBuffer[128]); // Byte +// GearNumGears
BoostAmount = (packetBuffer[129]); // Byte -// Boost // float // [ RANGE = 0.0f->100.0f ]
EnforcedPitStopLap = (packetBuffer[130]); // char // EnforcedPit
CrashState = (packetBuffer[131]); // Byte +// CrashState
OdometerKM1 = (packetBuffer[132]); // float // OdoKM 1st
OdometerKM2 = (packetBuffer[133]); // float // OdoKM 2nd
OdometerKM3 = (packetBuffer[134]); // float // OdoKM 3rd
OdometerKM4 = (packetBuffer[135]); // float // OdoKM 4th
Orientation = (packetBuffer[136]); // float // float Orientation[3]; //136
LocalVelocity = (packetBuffer[148]); // float // float LocalVelocity[3]; //148
WorldVelocity = (packetBuffer[160]); // float // float WorldVelocity[3]; //160
AngularVelocity = (packetBuffer[172]); // float // float AngularVelocity[3]; //172
LocalAcceleration = (packetBuffer[184]); // float // float LocalAcceleration[3]; //184
WorldAcceleration = (packetBuffer[196]); // float // float WorldAcceleration[3]; //196

// 200
ExtentsCentre = (packetBuffer[208]); // float // float ExtentsCentre[3]; //208
TyreFlags = (packetBuffer[220]); // Byte // byte TyreFlags[4];
Terrain = (packetBuffer[224]); // Byte // byte Terrain[4]; //224
TyreY = (packetBuffer[228]); // float // float TyreY[4]; //228
TyreRPS = (packetBuffer[244]); // float // float TyreRPS[4]; //244
TyreSlipSpeed = (packetBuffer[260]); // float // float TyreSlipSpeed[4]; //260
TyreTemps = (packetBuffer[276]); // Byte // byte TyreTemp[4]; // 276
tyreGrip0 = (packetBuffer[280]); // Byte // TyreGrip[0] //byte TyreGrip[4];
tyreGrip1 = (packetBuffer[281]); // Byte // TyreGrip[1]
tyreGrip2 = (packetBuffer[282]); // Byte // TyreGrip[2]
tyreGrip3 = (packetBuffer[283]); // Byte // TyreGrip[3]
TyreHeightAboveGround = (packetBuffer[284]); // float // float TyreHeightAboveGround[4]; // 284

// 300
TyreLateralStiffness = (packetBuffer[300]); // Byte // float TyreLateralStiffness[4]; // 300
TyreWear = (packetBuffer[316]); // Byte // byte TyreWear[4]; // 316
BrakeDamage1 = (packetBuffer[320]); // Byte +// byte BrakeDamage[4];
BrakeDamage2 = (packetBuffer[321]); // Byte +// byte BrakeDamage[4];
BrakeDamage3 = (packetBuffer[322]); // Byte +// byte BrakeDamage[4];
BrakeDamage4 = (packetBuffer[323]); // Byte +// byte BrakeDamage[4];
SuspensionDamage1 = (packetBuffer[324]); // Byte +// byte SuspensionDamage[4];
SuspensionDamage2 = (packetBuffer[325]); // Byte +// byte SuspensionDamage[4];
SuspensionDamage3 = (packetBuffer[326]); // Byte +// byte SuspensionDamage[4];
SuspensionDamage4 = (packetBuffer[327]); // Byte +// byte SuspensionDamage[4];
BrakeTempCelsius[4] = (packetBuffer[328]); // unsigned int // int BrakeTempCelsius[4]; // 328
TyreTreadTemp[4] = (packetBuffer[336]); // unsigned int // unsigned int TyreTreadTemp[4]; // 336
TyreLayerTemp[4] = (packetBuffer[344]); // unsigned int // unsigned int TyreLayerTemp[4]; // 344
TyreCarcassTemp[4] = (packetBuffer[352]); // unsigned int // unsigned int TyreCarcassTemp[4]; // 352
TyreRimTemp[4] = (packetBuffer[360]); // unsigned int // unsigned int TyreRimTemp[4]; // 360
TyreInternalAirTemp[4] = (packetBuffer[368]); // unsigned int // unsigned int TyreInternalAirTemp[4]; // 368
WheelLocalPositionY = (packetBuffer[376]); // float // float WheelLocalPositionY[4]; // 376
RideHeight = (packetBuffer[392]); // float // float RideHeight[4]; // 392

// 400+
SuspensionTravel = (packetBuffer[408]); // float // float SuspensionTravel[4]; // 408
SuspensionVelocity = (packetBuffer[424]); // float // float SuspensionVelocity[4]; // 424
AirPressure = (packetBuffer[440]); // unsigned int // unsigned int AirPressure[4];
eSpeed = (packetBuffer[448]); // float // EngineSpeed 1st // 448, 449, 450 & 451
etorque = (packetBuffer[452]); // float // Torque 1st // 452, 453, 454 & 455
AeroDamage = (packetBuffer[456]); // Byte +// AeroDamage // [ RANGE = 0.0f->1.0f ]
EngineDamage = (packetBuffer[457]); // Byte +// EngineDamage // [ RANGE = 0.0f->1.0f ]
AmbientTemperature = (packetBuffer[458]); // char // char AmbientTemperature; // 458
TrackTemperature = (packetBuffer[459]); // char // char TrackTemperature; // 459
RainDensity = (packetBuffer[460]); // Byte // byte RainDensity; // 460
WindSpeed = (packetBuffer[461]); // char // char WindSpeed; // 461
WindDirectionX = (packetBuffer[462]); // char // char WindDirectionX; // 462
WindDirectionY = (packetBuffer[463]); // char // char WindDirectionY; // 463
DPad = (packetBuffer[1366]); // Byte // byte DPad;

// Packetsize 1347
sCarName = (packetBuffer[3]); // char +// char sCarName[64];
sWorldPosition = (packetBuffer[0]); // Int // int sWorldPosition[3]; // 0 ???
sCurrentLapDistance = (packetBuffer[6]); // unsigned int // unsigned int sCurrentLapDistance; // 6 ???
sRacePosition = (packetBuffer[8]); // Byte // byte sRacePosition; // 8 ???
sLapsCompleted = (packetBuffer[9]); // Byte // byte sLapsCompleted; // 9 ???
sCurrentLap = (packetBuffer[10]); // Byte // byte sCurrentLap; // 10 ???
sSector = (packetBuffer[11]); // Byte // byte sSector; // 11 ???
sLastSectorTime = (packetBuffer[1]); // float // float sLastSectorTime; // 14 ???
sCarClassName = (packetBuffer[67]); // char +// char sCarClassName[64];
sTrackLocation = (packetBuffer[131]); // char +// char sTrackLocation[64];
sTrackVariation = (packetBuffer[195]); // char +// char sTrackVariation[64];
sName = (packetBuffer[259]); // char +// char sName[64]; or? char sName[16][64];

sFastestLapTime = (packetBuffer[1283]); // float // FastestLapTime 1st
//sFastestLapTime2 = (packetBuffer[xx]); // float // FastestLapTime 2nd
//sFastestLapTime3 = (packetBuffer[xx]); // float // FastestLapTime 3rd
//sFastestLapTime4 = (packetBuffer[xx]); // float // FastestLapTime 4th
*/


void_WiFi.h


//============================================================================
//= void WiFi.h
//============================================================================

//============================================================================
//= Serial print WiFi details
//============================================================================
void printWifiStatus() {

Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print the SSID of the network you're attached to:
// delay(500);
// Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // print your WiFi shield's IP address:


// print your WiFi shield's MAC address:
WiFi.macAddress(mac);
Serial.print("MAC: ");
Serial.print(mac[0], HEX);
Serial.print(":");
Serial.print(mac[1], HEX);
Serial.print(":");
Serial.print(mac[2], HEX);
Serial.print(":");
Serial.print(mac[3], HEX);
Serial.print(":");
Serial.print(mac[4], HEX);
Serial.print(":");
Serial.println(mac[5], HEX);

// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm");

}

//============================================================================
//= WiFi Connection
//============================================================================
void WiFiConnect() {
//WiFi.disconnect();
Serial.print("Reconnecting to :"); Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.setHostname("ESP32_Buttonbox"); // Name how device shows up in the Network
WiFi.begin(ssid, pass);

// Wait for connection
//for (int i = 0; i < 25; i++)
// {
if ( WiFi.status() != WL_CONNECTED ) {
/* delay ( 500 );
mcp1.digitalWrite(mcp1ledpinWiFi, LOW); // Turn Led WiFi MCP1 OFF

digitalWrite(ledpinWiFi, LOW); // Turn Led WiFi onboard OFF

delay ( 500 );
mcp1.digitalWrite(mcp1ledpinWiFi, HIGH); // Turn Led WiFi MCP1 ON
digitalWrite(ledpinWiFi, HIGH); // Turn Led WiFi onboard ON
*/
lcd1.init();
lcd1.backlight();
lcd1.clear();
lcd1.setCursor(0, 0); lcd1.print("Disconnected");
lcd1.setCursor(0, 1); lcd1.print("Reconnecting");
// module1.clearDisplay();
// }
}

// WiFi Successfully connected.
printWifiStatus(); // serialPrint WiFi details

// Print WiFi details to LCD
lcd1.init();
lcd1.backlight();
lcd1.clear();
lcd1.setCursor(0, 0); lcd1.print("SSID:"); lcd1.setCursor(5, 0); lcd1.print(WiFi.SSID());
lcd1.setCursor(0, 1); lcd1.print(WiFi.localIP());

delay ( 2000 );
lcd1.noBacklight();
lcd1.clear(); // Get LCD Ready for Gamestate
mcp1.digitalWrite(mcp1ledpinWiFi, HIGH); // Turn Led WiFi MCP1 ON
digitalWrite(ledpinWiFi, HIGH); // Turn Led WiFi onboard ON

}

Killg0re NL
26-03-2019, 11:53
Is there anyone who can help with the

FuelLevel and
TCS flag in CarFlags


with the Project Cars 2 protocol?

Maskmagog
26-03-2019, 17:10
I feel your pain, been struggling a lot with different UDP problems! I'm using FuelLevel without problem in PC2 protocol, but in C#. In Zeratall's library it's declared as a float, and read using C# float decoding (binaryReader.ReadSingle()). Then it's easy to reference it in my program. There might be more going on in the library, i can't say that I've studied it all, I'm just using it :)
If I remember correctly, you read the floats one digit/char at the time, and then decode it yourself? I'd highly recommend to find out how the built-in float decoder works. I'd guess that such function exists, though I can't say for certain.
FuelLevel should be a value between 0 (empty tank) and 1 (full tank).

Killg0re NL
26-03-2019, 19:29
The fuel level is working with protocol project cars 1 protocol. But the same code doesnt work when the game is set to project cars 2 protocol. But is should be working the same way. Same for the TCS bit.

Also there seems to be quite some delay before flags (light and ABS) are beiing set
With PC1 protocol, they are set immediatly.