diff --git a/speeduino/SD_logger.h b/speeduino/SD_logger.h new file mode 100644 index 00000000..38ee07b9 --- /dev/null +++ b/speeduino/SD_logger.h @@ -0,0 +1,32 @@ +#ifndef SD_H +#define SD_H + +#ifdef SD_LOGGING + +#include +#include + +#define SD_STATUS_OFF 0 +#define SD_STATUS_READY 1 +#define SD_STATUS_ERROR_NO_CARD 2 +#define SD_STATUS_ERROR_NO_FS 3 +#define SD_STATUS_ERROR_NO_WRITE 4 + +#ifdef CORE_TEENSY + #define SD_CS_PIN BUILTIN_SDCARD +#else + #define SD_CS_PIN 10 //This is a made up value for now +#endif + +//Sd2Card SD; +//SdVolume SD_volume; +File logFile; + +uint8_t SD_status = SD_STATUS_OFF; + +void initSD(); +void writeSDLog(); +void endSD(); + +#endif //SD_LOGGING +#endif //SD_H diff --git a/speeduino/SD_logger.ino b/speeduino/SD_logger.ino new file mode 100644 index 00000000..8d010198 --- /dev/null +++ b/speeduino/SD_logger.ino @@ -0,0 +1,34 @@ +#ifdef SD_LOGGING +#include +#include +#include "SD_logger.h" +#include "logger.h" + +void initSD() +{ + //Init the SPI connection to the card reader + if (SD.begin(SD_CS_PIN)) + { + //Attempt to create a log file for writing + logFile = SD.open("datalog.csv", FILE_WRITE); + if(!logFile) { SD_status = SD_STATUS_ERROR_NO_WRITE; } //Cannot write to SD card + else { SD_status = SD_STATUS_READY; } + } + else { SD_status = SD_STATUS_ERROR_NO_CARD; } + + + +} + +void endSD() +{ + +} + +void writeSDLog() +{ + uint8_t logEntry[LOG_ENTRY_SIZE]; + +} + +#endif \ No newline at end of file diff --git a/speeduino/comms.h b/speeduino/comms.h index e465a24d..561f4308 100644 --- a/speeduino/comms.h +++ b/speeduino/comms.h @@ -22,8 +22,6 @@ #define warmupPage 10 //Config Page 10 #define fuelMap2Page 11 -#define SERIAL_PACKET_SIZE 99 /**< The size of the live data packet. This MUST match ochBlockSize setting in the ini file */ - byte currentPage = 1;//Not the same as the speeduino config page numbers bool isMap = true; /**< Whether or not the currentPage contains only a 3D map that would require translation */ unsigned long requestCount = 0; /**< The number of times the A command has been issued. This is used to track whether a reset has recently been performed on the controller */ diff --git a/speeduino/comms.ino b/speeduino/comms.ino index d19ab6c5..3e83c66b 100644 --- a/speeduino/comms.ino +++ b/speeduino/comms.ino @@ -6,12 +6,12 @@ A full copy of the license may be found in the projects root directory #include "globals.h" #include "comms.h" #include "cancomms.h" -#include "errors.h" #include "storage.h" #include "maths.h" #include "utils.h" #include "decoders.h" #include "scheduledIO.h" +#include "logger.h" /* Processes the data on the serial buffer. @@ -39,7 +39,7 @@ void command() break; case 'A': // send x bytes of realtime values - sendValues(0, SERIAL_PACKET_SIZE, 0x30, 0); //send values to serial0 + sendValues(0, LOG_ENTRY_SIZE, 0x30, 0); //send values to serial0 break; @@ -495,7 +495,7 @@ This function returns the current values of a fixed group of variables //void sendValues(int packetlength, byte portNum) void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portNum) { - byte fullStatus[SERIAL_PACKET_SIZE]; + byte fullStatus[LOG_ENTRY_SIZE]; if (portNum == 3) { diff --git a/speeduino/globals.h b/speeduino/globals.h index 1147dfec..a6372903 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -19,6 +19,7 @@ #if defined(__MK64FX512__) || defined(__MK66FX1M0__) #define CORE_TEENSY35 #define BOARD_H "board_teensy35.h" + #define SD_LOGGING //SD logging enabled by default for Teensy 3.5 as it has the slot built in #elif defined(__IMXRT1062__) #define CORE_TEENSY40 #define BOARD_H "board_teensy40.h" diff --git a/speeduino/init.ino b/speeduino/init.ino index 7cc48e6c..1c15d4c6 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -1692,8 +1692,10 @@ void setPinMapping(byte boardID) pinFan = 25; //Pin for the fan output pinResetControl = 46; //Reset control output PLACEHOLDER value for now - pinMC33810_1_CS = 10; - pinMC33810_2_CS = 9; + #ifdef USE_MC33810 + pinMC33810_1_CS = 10; + pinMC33810_2_CS = 9; + #endif #endif break; diff --git a/speeduino/logger.h b/speeduino/logger.h new file mode 100644 index 00000000..41683a6a --- /dev/null +++ b/speeduino/logger.h @@ -0,0 +1,16 @@ +/** \file logger.h + * @brief File for generating log files and meta data + * @author Josh Stewart + * + * This file contains functions for creating a log file for use eith by TunerStudio directly or to be written to an SD card + * + */ + +#ifndef LOGGER_H +#define LOGGER_H + +#define LOG_ENTRY_SIZE 99 /**< The size of the live data packet. This MUST match ochBlockSize setting in the ini file */ + +void createLog(uint8_t *array); + +#endif \ No newline at end of file diff --git a/speeduino/logger.ino b/speeduino/logger.ino new file mode 100644 index 00000000..e71cf85a --- /dev/null +++ b/speeduino/logger.ino @@ -0,0 +1,123 @@ +#include "globals.h" +#include "errors.h" + +void createLog(uint8_t *logBuffer) +{ + currentStatus.spark ^= (-currentStatus.hasSync ^ currentStatus.spark) & (1U << BIT_SPARK_SYNC); //Set the sync bit of the Spark variable to match the hasSync variable + + logBuffer[0] = currentStatus.secl; //secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0) + logBuffer[1] = currentStatus.status1; //status1 Bitfield + logBuffer[2] = currentStatus.engine; //Engine Status Bitfield + logBuffer[3] = currentStatus.syncLossCounter; + logBuffer[4] = lowByte(currentStatus.MAP); //2 bytes for MAP + logBuffer[5] = highByte(currentStatus.MAP); + logBuffer[6] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //mat + logBuffer[7] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //Coolant ADC + logBuffer[8] = currentStatus.batCorrection; //Battery voltage correction (%) + logBuffer[9] = currentStatus.battery10; //battery voltage + logBuffer[10] = currentStatus.O2; //O2 + logBuffer[11] = currentStatus.egoCorrection; //Exhaust gas correction (%) + logBuffer[12] = currentStatus.iatCorrection; //Air temperature Correction (%) + logBuffer[13] = currentStatus.wueCorrection; //Warmup enrichment (%) + logBuffer[14] = lowByte(currentStatus.RPM); //rpm HB + logBuffer[15] = highByte(currentStatus.RPM); //rpm LB + logBuffer[16] = (byte)(currentStatus.AEamount >> 1); //TPS acceleration enrichment (%) divided by 2 (Can exceed 255) + logBuffer[17] = currentStatus.corrections; //Total GammaE (%) + logBuffer[18] = currentStatus.VE; //Current VE (%). Can be equal to VE1 or VE2 or a calculated value from both of them + logBuffer[19] = currentStatus.VE1; //VE 1 (%) + logBuffer[20] = currentStatus.VE2; //VE 2 (%) + logBuffer[21] = currentStatus.afrTarget; + logBuffer[22] = currentStatus.tpsDOT; //TPS DOT + logBuffer[23] = currentStatus.advance; + logBuffer[24] = currentStatus.TPS; // TPS (0% to 100%) + //Need to split the int loopsPerSecond value into 2 bytes + if(currentStatus.loopsPerSecond > 60000) { currentStatus.loopsPerSecond = 60000;} + logBuffer[25] = lowByte(currentStatus.loopsPerSecond); + logBuffer[26] = highByte(currentStatus.loopsPerSecond); + + //The following can be used to show the amount of free memory + currentStatus.freeRAM = freeRam(); + logBuffer[27] = lowByte(currentStatus.freeRAM); //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF); + logBuffer[28] = highByte(currentStatus.freeRAM); + + logBuffer[29] = (byte)(currentStatus.boostTarget >> 1); //Divide boost target by 2 to fit in a byte + logBuffer[30] = (byte)(currentStatus.boostDuty / 100); + logBuffer[31] = currentStatus.spark; //Spark related bitfield + + //rpmDOT must be sent as a signed integer + logBuffer[32] = lowByte(currentStatus.rpmDOT); + logBuffer[33] = highByte(currentStatus.rpmDOT); + + logBuffer[34] = currentStatus.ethanolPct; //Flex sensor value (or 0 if not used) + logBuffer[35] = currentStatus.flexCorrection; //Flex fuel correction (% above or below 100) + logBuffer[36] = currentStatus.flexIgnCorrection; //Ignition correction (Increased degrees of advance) for flex fuel + + logBuffer[37] = currentStatus.idleLoad; + logBuffer[38] = currentStatus.testOutputs; + + logBuffer[39] = currentStatus.O2_2; //O2 + logBuffer[40] = currentStatus.baro; //Barometer value + + logBuffer[41] = lowByte(currentStatus.canin[0]); + logBuffer[42] = highByte(currentStatus.canin[0]); + logBuffer[43] = lowByte(currentStatus.canin[1]); + logBuffer[44] = highByte(currentStatus.canin[1]); + logBuffer[45] = lowByte(currentStatus.canin[2]); + logBuffer[46] = highByte(currentStatus.canin[2]); + logBuffer[47] = lowByte(currentStatus.canin[3]); + logBuffer[48] = highByte(currentStatus.canin[3]); + logBuffer[49] = lowByte(currentStatus.canin[4]); + logBuffer[50] = highByte(currentStatus.canin[4]); + logBuffer[51] = lowByte(currentStatus.canin[5]); + logBuffer[52] = highByte(currentStatus.canin[5]); + logBuffer[53] = lowByte(currentStatus.canin[6]); + logBuffer[54] = highByte(currentStatus.canin[6]); + logBuffer[55] = lowByte(currentStatus.canin[7]); + logBuffer[56] = highByte(currentStatus.canin[7]); + logBuffer[57] = lowByte(currentStatus.canin[8]); + logBuffer[58] = highByte(currentStatus.canin[8]); + logBuffer[59] = lowByte(currentStatus.canin[9]); + logBuffer[60] = highByte(currentStatus.canin[9]); + logBuffer[61] = lowByte(currentStatus.canin[10]); + logBuffer[62] = highByte(currentStatus.canin[10]); + logBuffer[63] = lowByte(currentStatus.canin[11]); + logBuffer[64] = highByte(currentStatus.canin[11]); + logBuffer[65] = lowByte(currentStatus.canin[12]); + logBuffer[66] = highByte(currentStatus.canin[12]); + logBuffer[67] = lowByte(currentStatus.canin[13]); + logBuffer[68] = highByte(currentStatus.canin[13]); + logBuffer[69] = lowByte(currentStatus.canin[14]); + logBuffer[70] = highByte(currentStatus.canin[14]); + logBuffer[71] = lowByte(currentStatus.canin[15]); + logBuffer[72] = highByte(currentStatus.canin[15]); + + logBuffer[73] = currentStatus.tpsADC; + logBuffer[74] = getNextError(); + + logBuffer[75] = lowByte(currentStatus.PW1); //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS. + logBuffer[76] = highByte(currentStatus.PW1); //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS. + logBuffer[77] = lowByte(currentStatus.PW2); //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS. + logBuffer[78] = highByte(currentStatus.PW2); //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS. + logBuffer[79] = lowByte(currentStatus.PW3); //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS. + logBuffer[80] = highByte(currentStatus.PW3); //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS. + logBuffer[81] = lowByte(currentStatus.PW4); //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS. + logBuffer[82] = highByte(currentStatus.PW4); //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS. + + logBuffer[83] = currentStatus.status3; + + logBuffer[84] = currentStatus.nChannels; + logBuffer[85] = lowByte(currentStatus.fuelLoad); + logBuffer[86] = highByte(currentStatus.fuelLoad); + logBuffer[87] = lowByte(currentStatus.ignLoad); + logBuffer[88] = highByte(currentStatus.ignLoad); + logBuffer[89] = lowByte(currentStatus.dwell); + logBuffer[90] = highByte(currentStatus.dwell); + logBuffer[91] = currentStatus.CLIdleTarget; + logBuffer[92] = currentStatus.mapDOT; + logBuffer[93] = (int8_t)currentStatus.vvtAngle; + logBuffer[94] = currentStatus.vvtTargetAngle; + logBuffer[95] = currentStatus.vvtDuty; + logBuffer[96] = lowByte(currentStatus.flexBoostCorrection); + logBuffer[97] = highByte(currentStatus.flexBoostCorrection); + logBuffer[98] = currentStatus.baroCorrection; +} \ No newline at end of file