.
Dependencies: SDHCFileSystem mbed
main.cpp
00001 //CANcan.cpp 00002 //A dual canbus monitoring "blackbox" application for the Nissan Leaf 00003 //Dumps all messages to a file on the SDRAM 00004 //Todo: 00005 // Get timestamp on files 00006 // 00007 // Connections: 00008 //LEAF OBD 00009 //1: 00010 //2: 00011 //3: AVCAN-L White/Blue 00012 //4: 00013 //5: VSS Brown,White/Brown 00014 //6: CARCAN-H Green --> VP230b:7 00015 //7: 00016 //8: 12V-SW Orange,White/Orange 00017 //9: 00018 //10: 00019 //11: AVCAN-H Blue 00020 //12: EVCAN-L White/Grey --> VP230a:6 00021 //13: EVCAN-H Grey --> VP230a:7 00022 //14: CARCAN-L White/Green --> VP230b:6 00023 //15: 6V 00024 //16: 12V-AON Red/Blue,Blue/Red ----|<---- LPC1768:2 00025 //note 1: pins 4 & 5 longer 00026 //note 2: pins 12 & 13 next to key 00027 //note 3: pins 1 & 9 on right side looking into male connector with key on bottom 00028 00029 //VP230{a,b} 00030 //1:D 00031 //2:GND 00032 //3:VCC 00033 //4:R 00034 //5:Vref 00035 //6:CANL --> OBD:12,14 00036 //7:CANH --> OBD:13,6 00037 //8:RS --> LPC1768:27,28 00038 00039 //LPC1768 00040 //1: VSS 6V 00041 //2: VIN (4.5-9V supply) ---->|---- OBD:16 00042 //3: NC:VB 00043 //4: NC:nR 00044 //5: SPI:MOSI --> 6:SDRAM:DI 00045 //6: SPI:MISO --> 2:SDRAM:DO 00046 //7: SPI:SCLK --> 4:SDRAM:SCLK 00047 //8: CS --> 7:SDRAM:CS 00048 //9: CAN1:RX --> 4:CAN1:R 00049 //10: CAN1:TX --> 1:CAN1:D 00050 //11: NC:RS --> 4:LCD:RS 00051 //12: NC:E --> 6:LCD:E 00052 //13: NC:D4 --> 11:LCD:D4 00053 //14: NC:D5 --> 12:LCD:D5 00054 //15: NC:D6 --> 13:LCD:D6 00055 //16: NC:D7 --> 14:LCD:D7 00056 //17: CD --> 1:SDRAM:CD 00057 //18: NC:MON12V --> 4K to 12V, 1K to VSS (To be implemented) 00058 //19: PB2 00059 //20: PB1 00060 //21: NC:Spkr+ 00061 //22: NC:Spkr- (optional complimentary output for more volume) 00062 //23: NC:pwm 00063 //24: NC:LEDBLU --> 18:LCD:BLU (only used for tri-color displays) 00064 //25: NC:LEDGRN --> 17:LCD:GRN (only used for tri-color displays) 00065 //26: NC:LEDRED --> 16:LCD:RED 00066 //27: CAN1:Sleep --> 8:CAN1:RS 00067 //28: CAN2:Sleep --> 8:CAN2:RS 00068 //29: CAN2:TX --> 1:CAN2:D 00069 //30: CAN2:RX --> 4:CAN2:R 00070 //31: NC:USB_D+ 00071 //32: NC:USB_D- 00072 //33: NC:Eth_TD+ 00073 //34: NC:Eth_TD- 00074 //35: NC:Eth_RD+ 00075 //36: NC:Eth_RD- 00076 //37: NC:IF+ 00077 //38: NC:IF- 00078 //39: NC:5Vout (only available when connected as USB device) 00079 //40: VCC3.3 00080 // Set serial to 460800; RX:LF 00081 #include "mbed.h" 00082 #include "CAN.h" 00083 #include "SDHCFileSystem.h" 00084 00085 #define upLine "\033[1A" 00086 #define maxBufLen 2048 00087 #define canTimeout 5 00088 #define maxFileNum 30 00089 #define pollInt 60 00090 #define BatDataBaseG1 0x00 // 6 frames - SOH, SOC, Ah 00091 #define BatDataBaseG2 0x06 // 29 frames - Cell Pair data 00092 #define BatDataBaseG3 0x23 // 5 frames 00093 #define BatDataBaseG4 0x28 // 3 frames - Temperature data 00094 #define BatDataBaseG5 0x2B // 11 frames 00095 #define BatDataBaseG6 0x36 // 4 frames 00096 #define BatDataBaseG7 0x3A 00097 #define BatDataBufMax 0x196 // 7 x 3A bytes 00098 00099 //void Log (char *message); 00100 //void LogErr (char *message); 00101 //void autoPollISR(); 00102 //void sendReq(); 00103 extern "C" void mbed_reset(); 00104 00105 time_t seconds ; 00106 DigitalIn CD(p17); 00107 DigitalIn PB1( p20 ); 00108 SDFileSystem sd(p5, p6, p7, p8, "sd" ); // SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) 00109 Timer timer; 00110 DigitalOut led1(LED1); 00111 DigitalOut led2(LED2); 00112 DigitalOut led3(LED3); 00113 DigitalOut led4(LED4); 00114 CAN can1(p9, p10); // CAN1 uses pins 9 and 10 (rx, tx) and pin 27 (rs) 00115 DigitalOut can1_SleepMode(p27); // Use pin 27 to control the sleep mode of can1 00116 CAN can2(p30, p29); // CAN2 uses pins 30 and 29 (rx, tx) and pin 28 (rs) 00117 DigitalOut can2_SleepMode(p28); // Use pin 28 to control the sleep mode of can2 00118 bool logOpen = false; 00119 FILE *rfile; 00120 FILE *file; 00121 char fileName[35] = "" ; 00122 char writeBuffer[maxBufLen][13]; 00123 char c; 00124 volatile int writePointer = 0; 00125 volatile int secsIdle = 0; 00126 volatile bool canIdle = false; 00127 Serial pc(USBTX, USBRX); 00128 Ticker autoPoll; 00129 Ticker msgReq; 00130 unsigned char reqMsgCnt = 99; 00131 00132 extern "C" void RTC_IRQHandler() { 00133 timer.reset(); // zero ms at the-seconds-tic 00134 canIdle=(++secsIdle>canTimeout); 00135 LPC_RTC->ILR |= (1<<0); // clear interrupt to prepare for next 00136 } 00137 00138 extern "C" void RTC_Init (void) { 00139 LPC_RTC->ILR=0x00; // set up the RTC interrupts 00140 LPC_RTC->CIIR=0x01; // interrupts each second 00141 LPC_RTC->CCR = 0x01; // Clock enable 00142 //NVIC_SetPriority( RTC_IRQn, 10 ); 00143 NVIC_EnableIRQ( RTC_IRQn ); 00144 } 00145 00146 unsigned short getTimeStamp() { 00147 int msec = timer.read_ms() ; // read ms from the timer 00148 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900 00149 int isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC 00150 return ((isecs<<10)+msec) ; // return the two byte time stamp 00151 } 00152 00153 void readLog (){ 00154 unsigned char c; 00155 int i=0; 00156 char lastMsgNum[]={0,0}; 00157 char curMsgNum[]={0,0}; 00158 char canNum=0; 00159 pc.printf("printing file\n"); 00160 file = fopen(fileName, "r"); 00161 if (file == NULL) { 00162 pc.printf("no file found\n"); 00163 } 00164 while (!feof(file)) { 00165 c=fgetc(file); 00166 pc.printf("%02x ",c); 00167 if (i==0){ 00168 canNum=c; 00169 }else if (i==5){ 00170 curMsgNum[canNum]=c; 00171 } 00172 if (++i>12) { 00173 if (curMsgNum[canNum]>(lastMsgNum[canNum]+1)) { 00174 pc.printf(" ***"); 00175 } 00176 lastMsgNum[canNum]=curMsgNum[canNum]; 00177 pc.printf("\n"); 00178 i=0; 00179 } 00180 } 00181 pc.printf("\n\n"); 00182 fclose(file); 00183 } 00184 00185 void logCan (char mtype, CANMessage canRXmsg) { 00186 unsigned short ts = getTimeStamp(); 00187 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900 00188 if(canRXmsg.id>0) { 00189 writeBuffer[writePointer][0]=mtype; 00190 writeBuffer[writePointer][1]=((secs%60)<<2)+((ts&0x300)>>8); 00191 writeBuffer[writePointer][2]=ts&0xff; 00192 writeBuffer[writePointer][3]=canRXmsg.id&0xff; 00193 writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4); 00194 for (int i = 5; i<13; i++){ 00195 writeBuffer[writePointer][i]=canRXmsg.data[i-5]; 00196 } 00197 if (++writePointer >= maxBufLen) { 00198 writePointer = 0; 00199 led4 = !led4; 00200 } 00201 } 00202 } 00203 00204 void logTS () { 00205 CANMessage tsMsg; 00206 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900 00207 tsMsg.id=0xfff; 00208 tsMsg.len=0xf; 00209 tsMsg.data[0]=secs&0xff; 00210 tsMsg.data[1]=(secs>>8)&0xff; 00211 tsMsg.data[2]=(secs>>16)&0xff; 00212 tsMsg.data[3]=secs>>24; 00213 tsMsg.data[4]=0xff; 00214 tsMsg.data[5]=0xff; 00215 tsMsg.data[6]=0xff; 00216 tsMsg.data[7]=0xff; 00217 logCan(0,tsMsg); 00218 } 00219 void recieve1() { 00220 CANMessage msg1; 00221 secsIdle=0; // reset deadman switch 00222 can1.read(msg1); 00223 if(logOpen) 00224 logCan(2, msg1); 00225 led1 = !led1; 00226 } 00227 00228 void recieve2() { 00229 CANMessage msg2; 00230 secsIdle=0; // reset deadman switch 00231 can2.read(msg2); 00232 if(logOpen) 00233 logCan(1, msg2); 00234 led2 = !led2; 00235 } 00236 00237 void sendReq() { 00238 static char data[8] = {0x02, 0x21, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff}; 00239 if(reqMsgCnt<99){ 00240 switch (reqMsgCnt){ 00241 case BatDataBaseG1: 00242 can1.monitor(false); // set to active mode 00243 can1_SleepMode = 0; // enable TX 00244 data[0]=0x02; //change to request group 1 00245 data[1]=0x21; 00246 data[2]=0x01; 00247 break; 00248 case BatDataBaseG2: // group 1 has 6 frames 00249 data[0]=0x02; //change to request group 2 (cp data) 00250 data[1]=0x21; 00251 data[2]=0x02; 00252 break; 00253 case BatDataBaseG3: // group 2 has 29 frames 00254 data[0]=0x02; //change to request group 3 00255 data[1]=0x21; 00256 data[2]=0x03; 00257 break; 00258 case BatDataBaseG4: // group 3 has 5 frames 00259 data[0]=0x02; //change to request group 4 (temperature) 00260 data[1]=0x21; 00261 data[2]=0x04; 00262 break; 00263 case BatDataBaseG5: // group 4 has 3 frames 00264 data[0]=0x02; //change to request group 5 00265 data[1]=0x21; 00266 data[2]=0x05; 00267 break; 00268 case BatDataBaseG6: // group 4 has 3 frames 00269 data[0]=0x02; //change to request group 5 00270 data[1]=0x21; 00271 data[2]=0x06; 00272 break; 00273 case BatDataBaseG7: // group 5 has 11 frames 00274 reqMsgCnt = 99; 00275 can1_SleepMode = 1; // disable TX 00276 can1.monitor(true); // set to snoop mode 00277 msgReq.detach(); // stop ticker 00278 default: 00279 data[0]=0x30; //change to request next line message 00280 data[1]=0x01; 00281 data[2]=0x00; 00282 } 00283 can1.write(CANMessage(0x79b, data, 8)); 00284 reqMsgCnt++; 00285 } 00286 } 00287 00288 void autoPollISR(){ 00289 reqMsgCnt = 0; //reset message counter 00290 msgReq.attach(&sendReq,0.015); 00291 } 00292 00293 int main() { 00294 int readPointer=0; 00295 int fmon; 00296 int fday; 00297 int ftime; 00298 char sTemp[35]; 00299 unsigned long secs; 00300 bool bit = false; 00301 pc.baud(460800); // change serial interface to pc to 450800, 8N1 00302 can1.frequency(500000); 00303 can2.frequency(500000); 00304 can1_SleepMode = 1; // Monitor_only Mode 00305 can2_SleepMode = 1; // Monitor_only Mode 00306 CD.mode(PullUp) ; //SDRAM Chip Detect 00307 PB1.mode(PullUp) ; //Pushbutton 1 00308 can1.attach(&recieve1); 00309 can2.attach(&recieve2); 00310 autoPoll.attach(&autoPollISR,pollInt); // Poll battery data every 60 seconds 00311 msgReq.attach(&sendReq,0.015); // Each poll message separated by 15ms 00312 00313 timer.start() ; 00314 RTC_Init(); // start the RTC Interrupts that sync the timer 00315 00316 struct tm t; // pointer to a static tm structure 00317 00318 seconds = time(NULL); 00319 t = *localtime(&seconds) ; 00320 strftime(sTemp, 32, "%a %m/%d/%Y %X", &t); 00321 pc.printf("\nCurrent time set to: %s\n", sTemp); // DAY MM/DD/YYYY HH:MM:SS 00322 wait(1.1); // give time to sync 00323 00324 if (PB1==0) { //set time if pb pressed 00325 00326 pc.printf("\nEnter year (yyyy):"); 00327 pc.scanf("%s", &sTemp); 00328 t.tm_year = atoi(sTemp); 00329 00330 pc.printf("\nEnter month (mm):"); 00331 pc.scanf("%2s", &sTemp); 00332 t.tm_mon = atoi(sTemp); 00333 00334 pc.printf("\nEnter day (dd):"); 00335 pc.scanf("%2s", &sTemp); 00336 t.tm_mday = atoi(sTemp); 00337 00338 pc.printf("\nEnter hour (hh):"); 00339 pc.scanf("%2s", &sTemp); 00340 t.tm_hour = atoi(sTemp); 00341 00342 pc.printf("\nEnter minute (mm):"); 00343 pc.scanf("%2s", &sTemp); 00344 t.tm_min = atoi(sTemp); 00345 00346 pc.printf("\nEnter seconds (ss):"); 00347 pc.scanf("%2s", &sTemp); 00348 t.tm_sec = atoi(sTemp); 00349 00350 // adjust for tm structure required values 00351 t.tm_year = t.tm_year - 1900; 00352 t.tm_mon = t.tm_mon - 1; 00353 00354 // set the RTC 00355 set_time(mktime(&t)); 00356 seconds = time(NULL); 00357 00358 pc.printf("\nRTC set to: " ); 00359 strftime(sTemp, 32, "%a %m/%d/%Y %X", localtime(&seconds)); 00360 pc.printf("%s\n", sTemp); // DAY MM/DD/YYYY HH:MM:SS 00361 } 00362 00363 while (true) { 00364 if(CD == 1) { 00365 if (!logOpen) { // Open new file if one is not already open 00366 seconds = time(NULL); 00367 t = *localtime(&seconds) ; 00368 strftime(fileName, 32, "/sd/%m%d%H%M.alc", &t); //mmddhhmm.alc 00369 00370 pc.printf("Using file %s\n",fileName); 00371 file = fopen(fileName, "ab"); 00372 pc.printf("Using file2 %s\n",fileName); 00373 00374 if(file==NULL){ 00375 pc.printf("\nUnable to open canlog\n\n\n\n"); 00376 mbed_reset(); 00377 } else { 00378 logOpen = true; 00379 readPointer=writePointer; 00380 pc.printf("\nStarting Can Log %s\n",fileName); 00381 logTS(); 00382 fclose(file); 00383 file = fopen("/sd/loglog.txt", "a"); 00384 fprintf(file,"%s\r\n",fileName); 00385 fclose(file); 00386 } 00387 } // if (!logOpen) 00388 do { 00389 if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/2)||canIdle||(PB1==0)) { 00390 // Dump buffer if > 1/2 full, canbus has stopped, or PB1 pressed 00391 if (logOpen) { 00392 file = fopen(fileName, "ab"); 00393 if (file == NULL) { 00394 logOpen = false; 00395 pc.printf("Failed to append log file.\n\n"); 00396 } else { 00397 while (readPointer != writePointer) { 00398 for (int j = 0; j<13; j++){ 00399 fprintf(file,"%c",writeBuffer[readPointer][j]); 00400 } 00401 if(++readPointer >= maxBufLen) 00402 readPointer=0; 00403 } 00404 led3 = !led3; 00405 fclose(file); 00406 } 00407 } // if (logOpen) 00408 } // if > 1/2 full, canbus has stopped, or PB1 pressed 00409 if (canIdle) { // canbus idle --> sleep to save power 00410 // First take advantage of the idle time to clear some room 00411 00412 bit = false; 00413 rfile = fopen("/sd/loglog.txt", "r"); 00414 file = fopen("/sd/loglog.new", "w"); 00415 while (!feof(rfile)) { 00416 fscanf(rfile,"/sd/%2d%2d%4d.alc\r\n",&fmon,&fday,&ftime); 00417 //if ((fmon < 12) || (t.tm_mon > 1)){ 00418 // fday = fday + fmon*31; //crude - february will store 3 extra days of data 00419 //} 00420 //if ((fday+14)<(t.tm_mday+t.tm_mon*31)){ // Delete all files more than ~14 days old 00421 if (((fmon<=t.tm_mon)&&(fday<t.tm_mday))||(fmon>t.tm_mon+2)){ // Delete all files more than 1 month old 00422 bit=true; 00423 sprintf(sTemp,"/sd/%02d%02d%04d.alc",fmon,fday,ftime); 00424 if ((remove(sTemp)==NULL)) { 00425 pc.printf("Removed file %s\n",sTemp); 00426 } 00427 }else{ 00428 fprintf(file,"/sd/%02d%02d%04d.alc\r\n",fmon,fday,ftime); 00429 } 00430 } 00431 fclose (file); 00432 fclose (rfile); 00433 if (bit) { 00434 remove ("/sd/loglog.txt"); 00435 //rename not working so do it the hard way 00436 //rename ("/sd/loglog.new","/sd/loglog.txt"); 00437 rfile = fopen("/sd/loglog.new", "r"); 00438 file = fopen("/sd/loglog.txt", "w"); 00439 while (!feof(rfile)) { 00440 fscanf(rfile,"%s\r\n",&sTemp); 00441 fprintf(file,"%s\r\n",sTemp); 00442 } 00443 fclose (file); 00444 fclose (rfile); 00445 } 00446 remove ("/sd/loglog.new"); 00447 wait(5); // wait a few seconds to ensure SDRAM is done 00448 00449 pc.printf("Putting uC to sleep.\n"); 00450 //LPC_RTC->CIIR=0x00; // block RTC interrupts 00451 led1=0; 00452 led2=0; 00453 led3=0; 00454 led4=0; 00455 secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900 00456 while (secsIdle>canTimeout) { 00457 //DeepPowerDown(); 00458 __wfi(); // freeze CPU and wait for interrupt (from canbus) 00459 } 00460 canIdle=false; 00461 pc.printf("Waking uC.\n"); 00462 if (time(NULL)>(secs+1800)) { 00463 logOpen = false; // Start new file if asleep for more than 30 minutes 00464 } else { // insert timestamp on each wake 00465 logTS(); 00466 } 00467 //LPC_RTC->CIIR=0x01; // re-enable RTC interrupts 00468 } 00469 wait(0.2); // We get >2K messages per second 00470 } while ((PB1==1)&&(CD==1)&&logOpen); // keep going until button or SDram removed 00471 00472 if (PB1==0) { 00473 led1=0; 00474 led2=0; 00475 led3=0; 00476 led4=0; 00477 pc.printf("Log stopped\n\n"); 00478 logOpen=false; 00479 wait(5); // wait 5 seconds to give time to remove SDRAM if desired 00480 if (PB1==0) 00481 readLog(); // dump file if PB still pressed 00482 } 00483 } else { 00484 pc.printf("\nNo SDRAM Inserted.\n\n"); 00485 logOpen=false; 00486 led1=!led1; 00487 led2=led1; 00488 led3=led1; 00489 led4=led1; 00490 wait(5); 00491 } //if (CD==1) 00492 } //while (true) 00493 }
Generated on Mon Jul 25 2022 19:15:14 by 1.7.2