diff options
Diffstat (limited to 'nanotimer/datalogger.h')
-rw-r--r-- | nanotimer/datalogger.h | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/nanotimer/datalogger.h b/nanotimer/datalogger.h new file mode 100644 index 0000000..2c4ebfe --- /dev/null +++ b/nanotimer/datalogger.h @@ -0,0 +1,377 @@ +typedef enum { + LOG_TYPE_DEFAULT = 0, + LOG_TYPE_0_60, + LOG_TYPE_0_100, + LOG_TYPE_100_200, + LOG_TYPE_400M, + LOG_TYPE_LAPS, + LOG_TYPE_ROUTE, +} LOG_TYPES; + +#define FLAG_CAR 0x1 +#define FLAG_CYCLING 0x2 +#define FLAG_OBD 0x10 +#define FLAG_GPS 0x20 +#define FLAG_ACC 0x40 + +#define FORMAT_BIN 0 +#define FORMAT_CSV 1 + +typedef struct { + uint32_t time; + uint16_t pid; + uint8_t flags; + uint8_t checksum; + float value; +} LOG_DATA; + +typedef struct { + uint32_t time; + uint16_t pid; + uint8_t flags; + uint8_t checksum; + float value[3]; +} LOG_DATA_COMM; + +typedef struct { + uint32_t time; /* e.g. 1307281259 */ + uint16_t pid; + uint8_t message; + uint8_t checksum; + uint16_t fileIndex; + uint16_t fileSize; /* KB */ + uint16_t logFlags; + uint8_t logType; + uint8_t data[5]; +} LOG_DATA_FILE_INFO; + +typedef struct { + uint32_t time; + uint16_t pid; + uint8_t message; + uint8_t checksum; + uint8_t data[12]; +} LOG_DATA_COMMAND; + +typedef struct { + uint32_t id; + uint32_t dataOffset; + uint8_t ver; + uint8_t logType; + uint16_t flags; + uint32_t dateTime; //4, YYMMDDHHMM, e.g. 1305291359 + /* + uint8_t devid[8]; + uint8_t vin[24]; + uint8_t unused[84]; + */ +} HEADER; + +#define HEADER_LEN 128 /* bytes */ + +#define PID_GPS_COORDINATES 0xF00A +#define PID_GPS_ALTITUDE 0xF00C +#define PID_GPS_SPEED 0xF00D +#define PID_GPS_HEADING 0xF00E +#define PID_GPS_SAT_COUNT 0xF00F +#define PID_GPS_TIME 0xF010 + +#define PID_ACC 0xF020 +#define PID_GYRO 0xF021 + +#define PID_MESSAGE 0xFE00 +#define PID_HEART_BEAT 0xFFEE + +#define MSG_FILE_LIST_BEGIN 0x1 +#define MSG_FILE_LIST_END 0x2 +#define MSG_FILE_INFO 0x3 +#define MSG_FILE_REQUEST 0x4 + +#if LOG_FORMAT == FORMAT_BIN +#define FILE_NAME_FORMAT "/DAT%05d.LOG" +#else +#define FILE_NAME_FORMAT "/DAT%05d.CSV" +#endif + +#if ENABLE_DATA_OUT && !USE_OBD_BT +#if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) + SoftwareSerial mySerial(A8, A9); /* for BLE Shield on MEGA*/ +#elif defined(__AVR_ATmega644P__) + SoftwareSerial mySerial(9, 10); /* for Microduino */ +#else + SoftwareSerial mySerial(A2, A3); /* for BLE Shield on UNO*/ +#endif +#endif + +void btInit(int baudrate); +void btSend(byte* data, byte length); + +class CDataLogger { +public: + void initSender() + { +#if ENABLE_DATA_OUT +#if USE_OBD_BT + btInit(9600); +#else + mySerial.begin(9600); +#endif +#endif +#if ENABLE_DATA_LOG && LOG_FORMAT == FORMAT_CSV + m_lastDataTime = 0; +#endif + } +#if ENABLE_DATA_OUT + void sendFileInfo(File& file) + { + if (file.size() < HEADER_LEN) return; + + LOG_DATA_FILE_INFO info = {0}; + info.fileIndex = atol(file.name() + 3); + if (info.fileIndex == 0) return; + + HEADER hdr; + if (file.readBytes((char*)&hdr, sizeof(hdr)) != sizeof(hdr)) return; + + info.pid = PID_MESSAGE; + info.message = MSG_FILE_INFO; + info.fileSize = file.size(); + info.time = hdr.dateTime; + info.logType = hdr.logType; + info.logFlags = hdr.flags; + info.checksum = getChecksum((char*)&info, sizeof(info)); +#if USE_OBD_BT + btSend((uint8_t*)&info, sizeof(info)); +#else + mySerial.write((uint8_t*)&info, sizeof(info)); +#endif + } + void sendCommand(byte message, void* data = 0, byte bytes = 0) + { + LOG_DATA_COMMAND msg = {0, PID_MESSAGE, message}; + if (data) memcpy(msg.data, data, bytes); + msg.checksum = getChecksum((char*)&msg, sizeof(msg)); +#if USE_OBD_BT + btSend((uint8_t*)&msg, sizeof(msg)); +#else + mySerial.write((uint8_t*)&msg, sizeof(msg)); +#endif + } + bool receiveCommand(LOG_DATA_COMMAND& msg) + { +#if !USE_OBD_BT + if (!mySerial.available()) + return false; + + if (mySerial.readBytes((char*)&msg, sizeof(msg)) != sizeof(msg)) + return false; + + uint8_t checksum = msg.checksum; + msg.checksum = 0; + if (getChecksum((char*)&msg, sizeof(msg)) != msg.checksum) { + return false; + } +#endif + return true; + } +#endif + void logData(uint16_t pid, int value) + { + LOG_DATA_COMM ld = {dataTime, pid, 1, 0, value}; + ld.checksum = getChecksum((char*)&ld, 12); +#if ENABLE_DATA_OUT +#if USE_OBD_BT + btSend((uint8_t*)&ld, 12); +#else + mySerial.write((uint8_t*)&ld, 12); +#endif +#endif +#if ENABLE_DATA_LOG +#if LOG_FORMAT == FORMAT_BIN + sdfile.write((uint8_t*)&ld, 12); + dataSize += 12; +#else + dataSize += sdfile.print(dataTime - m_lastDataTime); + dataSize += sdfile.write(','); + dataSize += sdfile.print(pid, HEX); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value); + dataSize += sdfile.write('\n'); + m_lastDataTime = dataTime; +#endif +#endif + } + void logData(uint16_t pid, float value) + { + LOG_DATA_COMM ld = {dataTime, pid, 1, 0, value}; + ld.checksum = getChecksum((char*)&ld, 12); +#if ENABLE_DATA_OUT +#if USE_OBD_BT + btSend((uint8_t*)&ld, 12); +#else + mySerial.write((uint8_t*)&ld, 12); +#endif +#endif +#if ENABLE_DATA_LOG +#if LOG_FORMAT == FORMAT_BIN + sdfile.write((uint8_t*)&ld, 12); + dataSize += 12; +#else + dataSize += sdfile.print(dataTime - m_lastDataTime); + dataSize += sdfile.write(','); + dataSize += sdfile.print(pid, HEX); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value); + dataSize += sdfile.write('\n'); + m_lastDataTime = dataTime; +#endif +#endif + } + void logData(uint16_t pid, float value1, float value2) + { + LOG_DATA_COMM ld = {dataTime, pid, 2, 0, {value1, value2}}; + ld.checksum = getChecksum((char*)&ld, 16); +#if ENABLE_DATA_OUT +#if USE_OBD_BT + btSend((uint8_t*)&ld, 16); +#else + mySerial.write((uint8_t*)&ld, 16); +#endif +#endif +#if ENABLE_DATA_LOG +#if LOG_FORMAT == FORMAT_BIN + sdfile.write((uint8_t*)&ld, 16); + dataSize += 16; +#else + dataSize += sdfile.print(dataTime - m_lastDataTime); + dataSize += sdfile.write(','); + dataSize += sdfile.print(pid, HEX); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value1, 6); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value2, 6); + dataSize += sdfile.write('\n'); + m_lastDataTime = dataTime; +#endif +#endif + } + void logData(uint16_t pid, uint32_t value1, uint32_t value2) + { + LOG_DATA_COMM ld = {dataTime, pid, 2, 0, {value1, value2}}; + ld.checksum = getChecksum((char*)&ld, 16); +#if ENABLE_DATA_OUT +#if USE_OBD_BT + btSend((uint8_t*)&ld, 16); +#else + mySerial.write((uint8_t*)&ld, 16); +#endif +#endif +#if ENABLE_DATA_LOG +#if LOG_FORMAT == FORMAT_BIN + sdfile.write((uint8_t*)&ld, 16); + dataSize += 16; +#else + dataSize += sdfile.print(dataTime - m_lastDataTime); + dataSize += sdfile.write(','); + dataSize += sdfile.print(pid, HEX); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value1); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value2); + dataSize += sdfile.write('\n'); + m_lastDataTime = dataTime; +#endif +#endif + } + void logData(uint16_t pid, int value1, int value2, int value3) + { + LOG_DATA_COMM ld = {dataTime, pid, 3, 0, {value1, value2, value3}}; + ld.checksum = getChecksum((char*)&ld, 20); +#if ENABLE_DATA_OUT +#if USE_OBD_BT + btSend((uint8_t*)&ld, 20); +#else + mySerial.write((uint8_t*)&ld, 20); +#endif +#endif +#if ENABLE_DATA_LOG +#if LOG_FORMAT == FORMAT_BIN + sdfile.write((uint8_t*)&ld, 20); + dataSize += 20; +#else + dataSize += sdfile.print(dataTime - m_lastDataTime); + dataSize += sdfile.write(','); + dataSize += sdfile.print(pid, HEX); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value1); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value2); + dataSize += sdfile.write(','); + dataSize += sdfile.print(value3); + dataSize += sdfile.write('\n'); + m_lastDataTime = dataTime; +#endif +#endif + } +#if ENABLE_DATA_LOG + uint16_t openFile(LOG_TYPES logType, uint16_t logFlags = 0, uint32_t dateTime = 0) + { + uint16_t fileIndex; + char filename[24] = "/FRMATICS"; + + if (SD.exists(filename)) { + for (fileIndex = 1; fileIndex; fileIndex++) { + sprintf(filename + 9, FILE_NAME_FORMAT, fileIndex); + if (!SD.exists(filename)) { + break; + } + } + if (fileIndex == 0) + return 0; + } else { + SD.mkdir(filename); + fileIndex = 1; + sprintf(filename + 9, FILE_NAME_FORMAT, 1); + } + + sdfile = SD.open(filename, FILE_WRITE); + if (!sdfile) { + return 0; + } + +#if LOG_FORMAT == FORMAT_BIN + HEADER hdr = {'UDUS', HEADER_LEN, 1, logType, logFlags, dateTime}; + sdfile.write((uint8_t*)&hdr, sizeof(hdr)); + for (byte i = 0; i < HEADER_LEN - sizeof(hdr); i++) + sdfile.write((uint8_t)0); + dataSize = HEADER_LEN; +#endif + return fileIndex; + } + void closeFile() + { + sdfile.close(); + } + void flushFile() + { + sdfile.flush(); + } +#endif + uint32_t dataTime; + uint32_t dataSize; +private: + static byte getChecksum(char* buffer, byte len) + { + uint8_t checksum = 0; + for (byte i = 0; i < len; i++) { + checksum ^= buffer[i]; + } + return checksum; + } +#if ENABLE_DATA_LOG + File sdfile; +#if LOG_FORMAT == FORMAT_CSV + uint32_t m_lastDataTime; +#endif +#endif +}; |