vehicle CAN message log to SD file system using ring buffer memory

Dependencies:   SDFileSystem mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // CAN message log to SD card using can2.attach with ring buffer
00002 // 2013/Jan/25 using official SDFileSyatem library
00003 
00004 #include "mbed.h"
00005 #include "SDFileSystem.h"
00006 
00007 CAN can2(p30, p29);
00008 CANMessage can_MsgRx;
00009 Timer timer;
00010 
00011 // LED to know the status
00012 DigitalOut User_Led1(LED1);
00013 DigitalOut User_Led2(LED2);
00014 DigitalOut User_Led3(LED3);
00015 DigitalOut User_Led4(LED4);
00016 #define LED_ON 1
00017 #define LED_OFF 0
00018 
00019 // status monitor
00020 Serial pc(USBTX, USBRX); 
00021 
00022 SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs, name
00023 FILE *fp;
00024 int file_open = 0;
00025 
00026 // button switch for closing file
00027 DigitalIn button1(p16);
00028 DigitalIn button2(p17);
00029 DigitalIn button3(p18);
00030 DigitalIn button4(p19);
00031 int SW0 = 0x0f, SW1 = 0x0f, SW2 = 0x0f, BUTTON = 0;
00032 Ticker sw_check;
00033 
00034 // function prototypes
00035 void can_check(void);
00036 void check_sw();
00037 
00038 // CAN message ring buffer
00039 #define BUFFER_SIZE 512  // buffer size must be power of 2
00040 #define BUFFER_MASK ( BUFFER_SIZE - 1 )
00041 unsigned int second[BUFFER_SIZE];
00042 unsigned short can_id[BUFFER_SIZE];
00043 unsigned char msg_length[BUFFER_SIZE];
00044 unsigned char data[8][BUFFER_SIZE];
00045 volatile unsigned int head = 0;
00046 volatile unsigned int tail = 0;
00047 
00048 int main()
00049 {
00050     button1.mode(PullUp);
00051     button2.mode(PullUp);
00052     button3.mode(PullUp);
00053     button4.mode(PullUp);
00054     sw_check.attach_us(&check_sw, 5000);    // button switch status check every 5 msec
00055 
00056     can2.frequency(500000);
00057     pc.baud(9600);
00058     pc.printf("CAN log to SD card using ring buffer, 9600 bps\r\n");
00059 
00060     User_Led1 = LED_OFF;
00061     User_Led2 = LED_OFF;
00062     User_Led3 = LED_OFF;
00063     User_Led4 = LED_OFF;
00064 
00065     char file_name[20];
00066 
00067     time_t t;
00068     t = time( NULL ) + 32400;  // UTC + 9 hours for JST
00069     strftime( file_name, 20, "/sd/%y%m%d%H%M.log", localtime( &t ) );
00070     pc.printf( "log file is %s\r\n", file_name );
00071 
00072     fp = fopen(file_name, "w");
00073     if ( fp == NULL ) {
00074         pc.printf("Unable to create the file '%s'\r\n", file_name);
00075         pc.printf("Please try again\r\n");
00076 
00077         User_Led1 = LED_OFF;    // file open fail
00078         file_open = 0;
00079     } else {
00080         User_Led1 = LED_ON;     // file open
00081         file_open = 1;
00082     }
00083 
00084     timer.stop();
00085     timer.reset();
00086     timer.start();
00087     can2.attach(&can_check);
00088 
00089     int tmptail;
00090     while(1) {
00091         if ( head != tail ) {
00092             tmptail = (tail + 1) & BUFFER_MASK;
00093             fprintf(fp, "%03X,%03X,", head&0xfff, tmptail&0xfff);
00094             fprintf(fp, "%08X,", second[tmptail]);
00095             fprintf(fp, "t%03X%d", can_id[tmptail], msg_length[tmptail]);
00096 
00097             for (int i=0; i<msg_length[tmptail]; i++) {
00098                 fprintf(fp, "%02X", data[i][tmptail]);
00099             } // for
00100             fprintf(fp, "\r\n");
00101 
00102             tail = tmptail; // update tail after data sent
00103             if ( tail == 0 ) {
00104                 User_Led3 = !User_Led3;     // toggle led3 showing new cycle of ring buffer
00105                 t = time( NULL ) + 32400;   // UTC + 9 hours for JST
00106                 strftime( file_name, 20, "%T", localtime( &t ) );
00107                 pc.printf("new cycle of ring buffer at %s\r\n", file_name);
00108             }
00109         } // if head != tail
00110 
00111         if ( BUTTON&0x01 ) {    // button1 pressed
00112             BUTTON &= 0xfe;     // clear button status
00113             can2.attach(0);     // detach CAN interrupt
00114             file_open = 0;
00115             //Close the file
00116             fclose(fp);
00117             pc.printf("file closed\r\n");
00118             User_Led1 = LED_OFF;
00119         } // if button
00120     } // while
00121 } // main
00122 
00123 // read CAN2 message using intterupt and ring buffer
00124 void can_check(void) {
00125     int temp_head;
00126     if ( file_open == 1 ) {
00127         while ( can2.read(can_MsgRx) ) {
00128             temp_head = (head + 1) & BUFFER_MASK;
00129             if ( temp_head == tail ) {      // buffer overflow error
00130                 fclose(fp);
00131                 fprintf(stderr, "buffer overflow\r\n");
00132                 fprintf(stderr, "head = %d\r\n", head);
00133                 fprintf(stderr, "tail = %d\r\n", tail);
00134                 User_Led4 = 1;              // buffer overflow error
00135                 exit(1);
00136             } // if
00137 
00138             second[temp_head] = timer.read_us();
00139             can_id[temp_head] = can_MsgRx.id & 0xFFF;
00140             msg_length[temp_head] = can_MsgRx.len;
00141             for (int i=0; i<can_MsgRx.len; i++) {
00142                 data[i][temp_head] = can_MsgRx.data[i];
00143             } // for
00144             head = temp_head;   // update head after data stored
00145             User_Led2 = !User_Led2;     // toggle led2 showing CAN message reading
00146         } // while
00147     } // if open
00148 } // can_check
00149 
00150 // read switch status, called every 5 msec
00151 void check_sw() {
00152     SW2 = SW1;      // shift previous status
00153     SW1 = SW0;      // shift previous status
00154 // get new status
00155     SW0 = button1.read()+(button2.read()<<1)+(button3.read()<<2)+(button4.read()<<3);
00156 // following sequence detects switch press edge
00157 // HIGH(SW2) -> LOW(SW1) -> LOW(SW0)
00158     BUTTON |= ((~(SW0|SW1))&SW2);   // update button status
00159 } // check_sw