Fragt mithilfe des u-blox c027 über den CAN-Bus den Status der Batterieladung eines Think City Elektroautos ab und informiert per SMS den Halter. Bitte vor der ersten Verwendung die Handynummer anpassen. ---- Uses the u-blox c027 connected over can bus to a Think City electric car to inform a mobile number via SMS about the battery charging. Please change the mobile number to your mobile number before first use. Comments and messages are written in german.

Dependencies:   C027 C027_Support mbed

Revision:
0:4791fa520995
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Oct 18 12:03:43 2014 +0000
@@ -0,0 +1,471 @@
+/*
+   Dieses Programm überwacht die CAN Bus Nachrichten des Think City (Elektroauto). Es sendet beim aktivieren des u-blox C027 ein SMS mit dem aktuellen Status.
+   Ein weiteres SMS wird gesendet, wenn die Ladung abgebrochen oder beendet wurde.
+   Während des Ladevorgang kann der Status mit einer SMS abgefragt werden, dabei spielt der Inhalt der SMS keine Rolle, sie muss nur von der Nummer in der Variable strMobilenumber kommen.
+*/
+
+#include "mbed.h"
+#include "GPS.h"
+#include "MDM.h"
+#include "C027.h"
+C027 c027;
+CAN can1(CANRD, CANTD);
+void recieve1();
+
+// SIM PIN, NULL wenn keiner gesetzt wurde
+#define SIMPIN      NULL
+
+// APN für GPRS, wird momentan nicht verwendet
+#define APN         "gprs.swisscom.ch"
+
+// Benutzername für APN
+#define USERNAME    NULL
+
+// Passwort für APN
+#define PASSWORD    NULL 
+
+// Verhindert die Ausgabe von Debugnachrichten über USB, falls das Modem ebenfalls darüber arbeitet
+#define DOTRACE ((USBRX!=MDMRXD)&&(USBTX!=MDMTXD))
+#define TRACE     (!DOTRACE)?:printf
+
+// An die Nummer strMobilenumber werden die SMS gesendet und auch nur von dieser SMS akzeptiert
+char strMobilenumber[32] = "+41765377278";
+unsigned char idxSendSmsNow = 1;
+#define MAX_SMS_LEN  160
+
+// Endzeit
+time_t timeStop;
+
+/*
+intCarStatus:
+0 = Entladend
+1 = Ladend
+2 = Laden beendet
+3 = Laden abgebrochen
+4 = undefiniert
+
+float und int:
+999 = undefiniert
+
+char:
+4 = undefiniert
+*/
+unsigned char intCarStatus = 4;
+float         fltStartlevel = 999;
+
+// CAN Bus Daten
+float         fltSOC = 999;
+float         fltBatteryTemp = 999;
+unsigned int  intChargeLimitA = 999;
+float         fltBatteryV = 999;
+float         fltBatteryA = 999;
+float         fltBatteryMaxChargeA = 999;
+float         fltMaxChargeV = 999;
+unsigned int  intFailedCells = 999;
+float         fltBatteryTemp1 = 999;
+float         fltBatteryTemp2 = 999;
+unsigned int  intReleasedBatteries = 999;
+float         fltMinDischargeV = 999;
+float         fltMaxDischargeA = 999;
+float         fltChargerPwm = 999;
+float         fltMaxGeneratorV = 999;
+unsigned int  intHighEstErrCat = 999; // 0 = no faults, 1 = Reserved, 2 = Warning, 3 = Delayed switch off, 4 = immediate switch off
+float         fltPcuV = 999;
+float         fltSpeed = 999;
+float         fltPcuTemp = 999;
+unsigned int  intMainsV = 999;
+float         fltMainsA = 999;
+unsigned int  intBmiState = 999; // 0 = idle state, 1 = discharge state (contactor closed), 15 = fault state
+unsigned int  intBatteryType = 999;
+float         fltBmiTempError = 999;
+float         fltZebraTempError = 999;
+char          strShifter[24] = "00 00 00 00 00 00 00 00";
+/* char          str301[24] = "00 00 00 00 00 00 00 00";
+char          str302[24] = "00 00 00 00 00 00 00 00";
+char          str303[24] = "00 00 00 00 00 00 00 00";
+char          str304[24] = "00 00 00 00 00 00 00 00";
+char          str305[24] = "00 00 00 00 00 00 00 00";
+char          str311[24] = "00 00 00 00 00 00 00 00";
+char          str263[24] = "00 00 00 00 00 00 00 00"; */
+
+// Status
+unsigned char idxReducedNumberOfBatteries = 4;
+unsigned char idxEoc = 4;
+unsigned char idxSocGreater102 = 4;
+unsigned char idxChargeEn = 4;
+unsigned char idxOcvMeasurement = 4;
+unsigned char idxAc = 4;
+unsigned char idxChargeEnabled = 4;
+unsigned char idxFastChargeEnabled = 4;
+unsigned char idxDischargeEnabled = 4;
+unsigned char idxIsoTest = 4;
+unsigned char idxAcHeaterRelay = 4;
+unsigned char idxAcHeaterSwitch = 4;
+unsigned char idxRegenBrakeEnabled = 4;
+unsigned char idxDcDcEnabled = 4;
+unsigned char idxFanActive = 4;
+
+// Fehler
+unsigned char idxEpoEmerg = 4; // emergency power off happened
+unsigned char idxCrash = 4;
+unsigned char idxGeneralError = 4;
+unsigned char idxIntIsoError = 4;
+unsigned char idxExtIsoError = 4;
+unsigned char idxThermalIsoError = 4;
+unsigned char idxIsoError = 4;
+unsigned char idxTooManyFailedCells = 4;
+
+// Informationen
+unsigned char idxChargeWaitTempPCU = 4;
+unsigned char idxReachEocPlease = 4;
+unsigned char idxWaitTempDischarge = 4;
+unsigned char idxChargeWaitTempBattery = 4;
+
+// Warnungen
+unsigned char idxNoChargeCurrent = 4;
+unsigned char idxChargeOvervoltage = 4;
+unsigned char idxChargeOvercurrent = 4;
+
+unsigned char readBit(char strByte, char intRow) // Gibt ein Bit aus einem Byte aus, von rechts gezählt, intRow = 0 - 7
+{
+    return strByte >> intRow & 1;
+}
+
+int main(void)
+{
+    int intRet;
+#ifdef TARGET_LPC1768
+    char buf[2048] = "";
+#else
+    char buf[512] = "";
+#endif
+
+    // Startet die serielle Verbindung über USB, falls das Modem nicht über USB angeschlossen ist 
+    if (DOTRACE) {
+        Serial pc(USBTX,USBRX);
+        pc.baud(115200);
+    }
+    
+    wait_ms(1000);
+    
+    TRACE("GSMCAN startet...\r\n");
+    
+    // Schaltet das Modem und GPS ein
+    c027.mdmPower(true);
+    c027.gpsPower(true);
+
+    wait(2);
+    
+    // Erstellt das GPS Objekt
+#if GPSADR    // GPSI2C class
+    GPSI2C gps(GPSSDA,GPSSCL,GPSADR); 
+#elif GPSBAUD // GPSSerial class 
+    GPSSerial gps(GPSTXD,GPSRXD,GPSBAUD); 
+#else
+    #warning "Bitte GPS Pins definieren"
+#endif
+    
+    // Erstellt das Modem Objekt
+    MDMSerial mdm(MDMTXD,MDMRXD,MDMBAUD
+#if DEVICE_SERIAL_FC
+                ,MDMRTS,MDMCTS
+#endif
+                );
+    
+    // Initialisert das Modem
+    TRACE("Modem wird initialisiert...\r\n");
+    MDMParser::DevStatus devStatus;
+    MDMParser::NetStatus netStatus;
+    bool mdmOk = mdm.init(SIMPIN, &devStatus);
+    if (mdmOk)
+    {
+        if (DOTRACE) mdm.dumpDevStatus(&devStatus);
+        
+        // Wartet bis das Netz verbunden ist
+        TRACE("Warte auf GSM Netz...\r\n");
+        while (!mdm.checkNetStatus(&netStatus))
+            wait_ms(1000);
+    
+        if (DOTRACE) mdm.dumpNetStatus(&netStatus);
+    }
+    else {
+        // Wenn das Modem nicht gestartet werden kann, versuchen wir eine Neustart
+        TRACE("Modem Initialisierung fehlgeschlagen, Neustartversuch...\r\n");
+        c027.mdmReset();
+        wait(5);
+        mdmOk = mdm.init(SIMPIN, &devStatus);
+        if (DOTRACE) mdm.dumpDevStatus(&devStatus);
+        if (mdmOk) {
+            while (!mdm.checkNetStatus(&netStatus))
+            wait_ms(1000);
+            if (DOTRACE) mdm.dumpNetStatus(&netStatus);
+        }
+    }
+    TRACE("GSM Modem bereit, starte CAN\r\n");
+    DigitalOut can_standby(CANS);
+    can1.frequency(500000);
+    can1.mode(CAN::Normal);
+    can1.attach(&recieve1);
+    can_standby = 0;
+    
+    char link[128] = "";
+    unsigned int i = 0xFFFFFFFF;
+    const int wait = 100;
+    bool abort = false;
+    while (!abort) {
+        if (i == 10000/wait) {
+            while ((intRet = gps.getMessage(buf, sizeof(buf))) > 0)
+            {
+                int len = LENGTH(intRet);
+                if ((PROTOCOL(intRet) == GPSParser::NMEA) && (len > 6) && !strncmp("$GPGLL", buf, 6))
+                {
+                    double la = 0, lo = 0;
+                    char ch;
+                    if (gps.getNmeaAngle(1,buf,len,la) && 
+                        gps.getNmeaAngle(3,buf,len,lo) && 
+                        gps.getNmeaItem(6,buf,len,ch) && ch == 'A')
+                    {
+                        TRACE("GPS Location: %.5f %.5f\r\n", la, lo); 
+                        sprintf(link, "https://maps.google.com/?q=%.5f,%.5f", la, lo); 
+                    }
+                }
+            }
+        }
+        // Status bestimmen
+        if (fltSOC != 999 && idxAc != 4 && idxEoc != 4 && (i++ > 10000/wait)) {
+            i = 0;
+            if (idxAc == 1 && idxEoc == 0 && intCarStatus != 1) {
+                intCarStatus = 1;
+                fltStartlevel = fltSOC;
+                set_time(1);
+                TRACE("Ladend; Anfangsstand: %.1f%%\r\n", fltStartlevel);
+            }
+            else if (idxEoc == 1 && intCarStatus <= 1) {
+                intCarStatus = 2;
+                timeStop = time(NULL)/60;
+                TRACE("Laden beendet; Anfangsstand: %.1f%%; Zeit: %d Minuten\r\n", fltStartlevel, timeStop);
+                if (fltStartlevel < 90) {
+                    idxSendSmsNow = 1;
+                }
+            }
+            else if (idxAc == 0 && intCarStatus == 1) {
+                intCarStatus = 3;
+                timeStop = time(NULL)/60;
+                TRACE("Laden abgebrochen; Anfangsstand: %.1f%%; Zeit: %d Minuten\r\n", fltStartlevel, timeStop);
+                if (timeStop > 1) {
+                    idxSendSmsNow = 1;
+                }
+            }
+            else if (idxAc == 0 && intCarStatus == 2) {
+                intCarStatus = 0;
+                fltStartlevel = fltSOC;
+                TRACE("Entladend; Anfangsstand: %.1f%%\r\n", fltStartlevel);
+            }
+            if (intCarStatus == 4 && idxAc == 0) {
+                intCarStatus = 0;
+                fltStartlevel = fltSOC;
+                TRACE("Entladend; Anfangsstand: %.1f%%\r\n", fltStartlevel);
+            }
+            else if (intCarStatus == 4 && idxEoc == 1) {
+                intCarStatus = 2;
+                fltStartlevel = fltSOC;
+                TRACE("Laden beendet; Anfangsstand: %.1f%%\r\n", fltStartlevel);
+            }
+            else if (intCarStatus == 4 && idxAc == 1 && idxEoc == 0) {
+                intCarStatus = 1;
+                fltStartlevel = fltSOC;
+                set_time(1);
+                TRACE("Ladend; Anfangsstand: %.1f%%\r\n", fltStartlevel);
+            }
+            switch (intCarStatus) {
+                case 0:
+                    TRACE("Entladend; Anfangsstand: %.1f%%; Stand: %.1f%%; PCU: %.1fV\r\n", fltStartlevel, fltSOC, fltPcuV);
+                    break;
+                case 1:
+                    TRACE("Ladend; Anfangsstand: %.1f%%; Stand: %.1f%%; PCU: %.1fV\r\n", fltStartlevel, fltSOC, fltPcuV);
+                    break;
+                case 2:
+                    TRACE("Laden beendet; Anfangsstand: %.1f%%; Zeit: %d Minuten; PCU: %.1fV\r\n", fltStartlevel, timeStop, fltPcuV);
+                    break;
+                case 3:
+                    TRACE("Laden abgebrochen; Anfangsstand: %.1f%%; Schlussstand: %.1f%%; Zeit: %d Minuten; PCU: %.1fV\r\n", fltStartlevel, fltSOC, timeStop, fltPcuV);
+                    break;
+                case 4:
+                    TRACE("undefiniert;\r\n");
+                    break;
+            }
+            if (mdmOk) {
+                // Status des GSM Modems ausgeben
+                if (mdm.checkNetStatus(&netStatus)) {
+                    if (DOTRACE) mdm.dumpNetStatus(&netStatus);
+                }
+                    
+                // Ungelesene SMS prüfen
+                int ix[8];
+                int n = mdm.smsList("REC UNREAD", ix, 8);
+                if (8 < n) n = 8;
+                while (0 < n--)
+                {
+                    char num[32];
+                    if (mdm.smsRead(ix[n], num, buf, sizeof(buf))) {
+                        TRACE("SMS von \"%s\" mit dem Text \"%s\"\r\n", num, buf);
+                        TRACE("Loesche SMS %d\r\n", ix[n]);
+                        mdm.smsDelete(ix[n]);
+                        // Sende den aktuellen Status, wenn die SMS von der strMobilenumber gekommen ist
+                        if (strcmp(num, strMobilenumber)==0) {
+                            idxSendSmsNow = 1;
+                        }
+                    }
+                }
+            }
+            if (mdmOk && idxSendSmsNow == 1 && intCarStatus != 4) {
+                idxSendSmsNow = 0;
+                char strReply[160];
+                switch (intCarStatus) {
+                case 0:
+                    snprintf(strReply, MAX_SMS_LEN, "Entladend; Anfangsstand: %.1f%%; Stand: %.1f%%; PCU: %.1fV; %s", fltStartlevel, fltSOC, fltPcuV, link);
+                    mdm.smsSend(strMobilenumber, strReply);
+                    break;
+                case 1:
+                    snprintf(strReply, MAX_SMS_LEN, "Ladend; Anfangsstand: %.1f%%; Stand: %.1f%%; PCU: %.1fV; %s", fltStartlevel, fltSOC, fltPcuV, link);
+                    mdm.smsSend(strMobilenumber, strReply);
+                    break;
+                case 2:
+                    snprintf(strReply, MAX_SMS_LEN, "Laden beendet; Anfangsstand: %.1f%%; Zeit: %d Minuten; PCU: %.1fV; %s", fltStartlevel, timeStop, fltPcuV, link);
+                    mdm.smsSend(strMobilenumber, strReply);
+                    break;
+                case 3:
+                    snprintf(strReply, MAX_SMS_LEN, "Laden abgebrochen; Anfangsstand: %.1f%%; Schlussstand: %.1f%%; Zeit: %d Minuten; PCU: %.1fV; %s", fltStartlevel, fltSOC, timeStop, fltPcuV, link);
+                    mdm.smsSend(strMobilenumber, strReply);
+                    intCarStatus = 0;
+                    fltStartlevel = fltSOC;
+                }
+                TRACE("Sende SMS-Antwort \"%s\" an \"%s\"\r\n", strReply, strMobilenumber);
+                delete[] strReply;
+            }
+            // Gebe den aktuellen Status aller CAN Bus Nachrichten aus
+            //TRACE("0x301: str301=%s\r\n", str301);
+            TRACE("0x301: fltBatteryA=%.1f, fltBatteryV=%.1f, fltSOC=%.1f, fltBatteryTemp=%.1f\r\n", fltBatteryA, fltBatteryV, fltSOC, fltBatteryTemp);
+            //TRACE("0x302: str302=%s\r\n", str302);
+            TRACE("0x302: idxGeneralError=%d, idxIsoError=%d, fltMinDischargeV=%.1f, fltMaxDischargeA=%.1f\r\n", idxGeneralError, idxIsoError, fltMinDischargeV, fltMaxDischargeA);
+            //TRACE("0x303: str303=%s\r\n", str303);
+            TRACE("0x303: fltBatteryMaxChargeA=%.1f, fltMaxChargeV=%.1f, idxChargeEnabled=%d, idxRegenBrakeEnabled=%d, idxDischargeEnabled=%d, idxFastChargeEnabled=%d, idxDcDcEnabled=%d, idxAc=%d, intReleasedBatteries=%d, idxReducedNumberOfBatteries=%d, idxEpoEmerg=%d, idxCrash=%d, idxFanActive=%d, idxSocGreater102=%d, idxIsoTest=%d, idxChargeWaitTempPCU=%d\r\n", fltBatteryMaxChargeA, fltMaxChargeV, idxChargeEnabled, idxRegenBrakeEnabled, idxDischargeEnabled, idxFastChargeEnabled, idxDcDcEnabled, idxAc, intReleasedBatteries, idxReducedNumberOfBatteries, idxEpoEmerg, idxCrash, idxFanActive, idxSocGreater102, idxIsoTest, idxChargeWaitTempPCU);
+            //TRACE("0x304: str304=%s\r\n", str304);
+            TRACE("0x304: fltMaxGeneratorV=%.1f, intHighEstErrCat=%d, idxEoc=%d, idxReachEocPlease=%d, idxChargeWaitTempBattery=%d, idxTooManyFailedCells=%d, idxAcHeaterRelay=%d, idxAcHeaterSwitch=%d, fltBatteryTemp1=%.1f, fltBatteryTemp2=%.1f\r\n", fltMaxGeneratorV, intHighEstErrCat, idxEoc, idxReachEocPlease, idxChargeWaitTempBattery, idxTooManyFailedCells, idxAcHeaterRelay, idxAcHeaterSwitch, fltBatteryTemp1, fltBatteryTemp2);
+            //TRACE("0x305: str305=%s\r\n", str305);
+            TRACE("0x305: fltChargerPwm=%.1f, idxIntIsoError=%d, idxExtIsoError=%d, idxChargeEn=%d, idxOcvMeasurement=%d, idxNoChargeCurrent=%d, idxChargeOvervoltage=%d, idxChargeOvercurrent=%d, intFailedCells=%d, idxWaitTempDischarge=%d, idxThermalIsoError=%d, intBmiState=%d, intBatteryType=%d, fltBmiTempError=%.1f, fltZebraTempError=%.1f\r\n", fltChargerPwm, idxIntIsoError, idxExtIsoError, idxChargeEn, idxOcvMeasurement, idxNoChargeCurrent, idxChargeOvervoltage, idxChargeOvercurrent, intFailedCells, idxWaitTempDischarge, idxThermalIsoError, intBmiState, intBatteryType, fltBmiTempError, fltZebraTempError);
+            //TRACE("0x311: str311=%s\r\n", str311);
+            TRACE("0x311: intChargeLimitA=%d\r\n", intChargeLimitA);
+            //TRACE("0x263: str263=%s\r\n", str263);
+            TRACE("0x263: fltPcuV=%.1f, fltSpeed=%.1f, fltPcuTemp=%.1f, intMainsV=%d, fltMainsA=%.1f\r\n", fltPcuV, fltSpeed, fltPcuTemp, intMainsV, fltMainsA);
+            TRACE("0x264: strShifter=%s\r\n", strShifter);
+        }
+        wait_ms(wait);
+    }
+    mdm.powerOff();
+    gps.powerOff();
+    TRACE("Schalte Modem und GPS aus...\r\n");
+#ifdef C027_USEONBOARD
+    c027.mdmPower(false);
+    c027.gpsPower(false);
+#endif    
+    return 0;
+}
+
+// Hier werden die CAN Nachrichten verarbeitet und in die Variablen gespeichert
+void recieve1() {
+    CANMessage canMsg;
+    if (can1.read(canMsg)) {
+       switch (canMsg.id) {
+       case 0x301:
+         fltBatteryA = ((float)(((int) canMsg.data[0] << 8) + canMsg.data[1]) / 10);
+         fltBatteryV = ((float)(((int) canMsg.data[2] << 8) + canMsg.data[3]) / 10);
+         fltSOC = 100.0f - ((float)(((int) canMsg.data[4] << 8) + canMsg.data[5]) / 10);
+         fltBatteryTemp = ((float)(((int) canMsg.data[6] << 8) + canMsg.data[7]) / 10);
+         //snprintf(str301, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+         break;
+       case 0x302:
+         idxGeneralError = readBit(canMsg.data[0], 0);
+         idxIsoError = readBit(canMsg.data[2], 0);
+         fltMinDischargeV = ((float)(((int) canMsg.data[4] << 8) + canMsg.data[5]) / 10);
+         fltMaxDischargeA = ((float)(((int) canMsg.data[6] << 8) + canMsg.data[7]) / 10);
+         //snprintf(str302, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+         break;
+       case 0x303:
+         fltBatteryMaxChargeA = ((float)(((int) canMsg.data[0] << 8) + canMsg.data[1]) / 10);
+         fltMaxChargeV = ((float)(((int) canMsg.data[2] << 8) + canMsg.data[3]) / 10);
+         idxChargeEnabled = readBit(canMsg.data[4], 0);
+         idxRegenBrakeEnabled = readBit(canMsg.data[4], 1);
+         idxDischargeEnabled = readBit(canMsg.data[4], 2);
+         idxFastChargeEnabled = readBit(canMsg.data[4], 3);
+         idxDcDcEnabled = readBit(canMsg.data[4], 4);
+         idxAc = readBit(canMsg.data[4], 5);
+         intReleasedBatteries = canMsg.data[5];
+         idxReducedNumberOfBatteries = readBit(canMsg.data[6], 0);
+         idxEpoEmerg = readBit(canMsg.data[6], 3);
+         idxCrash = readBit(canMsg.data[6], 4);
+         idxFanActive = readBit(canMsg.data[6], 5);
+         idxSocGreater102 = readBit(canMsg.data[6], 6);
+         idxIsoTest = readBit(canMsg.data[6], 7);
+         idxChargeWaitTempPCU = readBit(canMsg.data[7], 0);
+         //snprintf(str303, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+         break;
+       case 0x304:
+         fltMaxGeneratorV = ((float)(((int) canMsg.data[0] << 8) + canMsg.data[1]) / 10);
+         intHighEstErrCat = ((unsigned char) canMsg.data[2]);
+         idxEoc = readBit(canMsg.data[3], 0);
+         idxReachEocPlease = readBit(canMsg.data[3], 1);
+         idxChargeWaitTempBattery = readBit(canMsg.data[3], 2);
+         idxTooManyFailedCells = readBit(canMsg.data[3], 3);
+         idxAcHeaterRelay = readBit(canMsg.data[3], 4);
+         idxAcHeaterSwitch = readBit(canMsg.data[3], 5);
+         fltBatteryTemp1 = ((float)(((int) canMsg.data[4] << 8) + canMsg.data[5]) / 10);
+         fltBatteryTemp2 = ((float)(((int) canMsg.data[6] << 8) + canMsg.data[7]) / 10);
+         //snprintf(str304, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+         break;
+       case 0x305:
+         fltChargerPwm = ((float)(((int) canMsg.data[0] << 8) + canMsg.data[1]) / 10);
+         intBmiState = canMsg.data[2] & 15;
+         idxIntIsoError = readBit(canMsg.data[2], 4);
+         idxExtIsoError = readBit(canMsg.data[2], 5);
+         idxChargeEn = readBit(canMsg.data[3], 0);
+         idxOcvMeasurement = readBit(canMsg.data[3], 1);
+         idxNoChargeCurrent = readBit(canMsg.data[3], 2);
+         idxChargeOvervoltage = readBit(canMsg.data[3], 3);
+         idxChargeOvercurrent = readBit(canMsg.data[3], 4);
+         intFailedCells = ((int) canMsg.data[4]<<8) + canMsg.data[5];
+         idxWaitTempDischarge = readBit(canMsg.data[6], 6);
+         idxThermalIsoError = readBit(canMsg.data[6], 5);
+         intBatteryType = (canMsg.data[3] & 224) * 0.03125;
+         fltBmiTempError = (canMsg.data[6] & 6) / 2;
+         fltZebraTempError = (canMsg.data[6] & 24) * 0.125;
+         //snprintf(str305, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+         break;
+       case 0x311:
+         intChargeLimitA = ((unsigned char) canMsg.data[1]) * 0.2 ;
+         //snprintf(str311, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+         break;
+       case 0x263:
+         fltPcuV = ((float)((int) canMsg.data[3]) / 10);
+         fltSpeed = ((float)((int) canMsg.data[5]) / 2);
+         fltPcuTemp = ((float)((int) canMsg.data[2]) / 2);
+         intMainsV = ((unsigned char) canMsg.data[1]);
+         fltMainsA = ((float)((int) canMsg.data[0]) * 2 / 10);
+         //snprintf(str263, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+         break;
+       case 0x264:
+         snprintf(strShifter, 24, "%X %X %X %X %X %X %X %X" , canMsg.data[0], canMsg.data[1], canMsg.data[2], canMsg.data[3], canMsg.data[4], canMsg.data[5], canMsg.data[6], canMsg.data[7]);
+       // Mit folgendem Block können alle unbekannten Nachrichten ausgegeben werden, bremst allerdings das Programm merklich ab
+       /* default:
+         TRACE("ID: 0x%x", canMsg.id);
+         TRACE(" Len: %d", canMsg.len);
+         TRACE(" Type: %d", canMsg.type);
+         TRACE(" Format: %d", canMsg.format);
+         TRACE(" Data:");
+         for (int count = 0; count < canMsg.len; count++) {
+             TRACE(" %x", canMsg.data[count]);
+         }
+         TRACE("\r\n"); */
+       }
+    }
+}
\ No newline at end of file