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

Dependencies:   SDFileSystem mbed

Committer:
ym1784
Date:
Fri Jan 25 21:04:19 2013 +0000
Revision:
0:de9553dd79ec
Child:
1:4a538cae9042
initial version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ym1784 0:de9553dd79ec 1 // CAN message log to SD card using can2.attach with ring buffer
ym1784 0:de9553dd79ec 2 // 2013/Jan/25 using official SDFileSyatem library
ym1784 0:de9553dd79ec 3
ym1784 0:de9553dd79ec 4 #include "mbed.h"
ym1784 0:de9553dd79ec 5 #include "SDFileSystem.h"
ym1784 0:de9553dd79ec 6
ym1784 0:de9553dd79ec 7 CAN can2(p30, p29);
ym1784 0:de9553dd79ec 8 CANMessage can_MsgRx;
ym1784 0:de9553dd79ec 9 Timer timer;
ym1784 0:de9553dd79ec 10
ym1784 0:de9553dd79ec 11 // LED to know the status
ym1784 0:de9553dd79ec 12 DigitalOut User_Led1(LED1);
ym1784 0:de9553dd79ec 13 DigitalOut User_Led2(LED2);
ym1784 0:de9553dd79ec 14 DigitalOut User_Led3(LED3);
ym1784 0:de9553dd79ec 15 DigitalOut User_Led4(LED4);
ym1784 0:de9553dd79ec 16 #define LED_ON 1
ym1784 0:de9553dd79ec 17 #define LED_OFF 0
ym1784 0:de9553dd79ec 18
ym1784 0:de9553dd79ec 19 // status monitor
ym1784 0:de9553dd79ec 20 Serial pc(USBTX, USBRX);
ym1784 0:de9553dd79ec 21
ym1784 0:de9553dd79ec 22 SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs, name
ym1784 0:de9553dd79ec 23 FILE *fp;
ym1784 0:de9553dd79ec 24 int file_open = 0;
ym1784 0:de9553dd79ec 25
ym1784 0:de9553dd79ec 26 // button switch for closing file
ym1784 0:de9553dd79ec 27 DigitalIn button1(p16);
ym1784 0:de9553dd79ec 28 DigitalIn button2(p17);
ym1784 0:de9553dd79ec 29 DigitalIn button3(p18);
ym1784 0:de9553dd79ec 30 DigitalIn button4(p19);
ym1784 0:de9553dd79ec 31 int SW0 = 0x0f, SW1 = 0x0f, SW2 = 0x0f, BUTTON = 0;
ym1784 0:de9553dd79ec 32 Ticker sw_check;
ym1784 0:de9553dd79ec 33
ym1784 0:de9553dd79ec 34 // function prototypes
ym1784 0:de9553dd79ec 35 void can_check(void);
ym1784 0:de9553dd79ec 36 void check_sw();
ym1784 0:de9553dd79ec 37
ym1784 0:de9553dd79ec 38 // CAN message buffer
ym1784 0:de9553dd79ec 39 #define BUFFER_SIZE 512 // buffer size must be power of 2
ym1784 0:de9553dd79ec 40 #define BUFFER_MASK ( BUFFER_SIZE - 1 )
ym1784 0:de9553dd79ec 41 unsigned int second[BUFFER_SIZE];
ym1784 0:de9553dd79ec 42 unsigned short can_id[BUFFER_SIZE];
ym1784 0:de9553dd79ec 43 unsigned char msg_length[BUFFER_SIZE];
ym1784 0:de9553dd79ec 44 unsigned char data[8][BUFFER_SIZE];
ym1784 0:de9553dd79ec 45 volatile unsigned int head = 0;
ym1784 0:de9553dd79ec 46 volatile unsigned int tail = 0;
ym1784 0:de9553dd79ec 47
ym1784 0:de9553dd79ec 48 int main()
ym1784 0:de9553dd79ec 49 {
ym1784 0:de9553dd79ec 50 button1.mode(PullUp);
ym1784 0:de9553dd79ec 51 button2.mode(PullUp);
ym1784 0:de9553dd79ec 52 button3.mode(PullUp);
ym1784 0:de9553dd79ec 53 button4.mode(PullUp);
ym1784 0:de9553dd79ec 54 sw_check.attach_us(&check_sw, 5000); // status check every 5 msec
ym1784 0:de9553dd79ec 55
ym1784 0:de9553dd79ec 56 can2.frequency(500000);
ym1784 0:de9553dd79ec 57 pc.baud(9600);
ym1784 0:de9553dd79ec 58 pc.printf("CAN log to SD card using ring buffer, 9600 bps\r\n");
ym1784 0:de9553dd79ec 59
ym1784 0:de9553dd79ec 60 User_Led1 = LED_OFF;
ym1784 0:de9553dd79ec 61 User_Led2 = LED_OFF;
ym1784 0:de9553dd79ec 62 User_Led3 = LED_OFF;
ym1784 0:de9553dd79ec 63 User_Led4 = LED_OFF;
ym1784 0:de9553dd79ec 64
ym1784 0:de9553dd79ec 65 char file_name[20];
ym1784 0:de9553dd79ec 66
ym1784 0:de9553dd79ec 67 time_t t;
ym1784 0:de9553dd79ec 68 t = time( NULL ) + 32400; // UTC + 9 hours for JST
ym1784 0:de9553dd79ec 69 strftime( file_name, 20, "/sd/%y%m%d%H%M.log", localtime( &t ) );
ym1784 0:de9553dd79ec 70 pc.printf( "log file is %s\r\n", file_name );
ym1784 0:de9553dd79ec 71
ym1784 0:de9553dd79ec 72 fp = fopen(file_name, "w");
ym1784 0:de9553dd79ec 73 if ( fp == NULL ) {
ym1784 0:de9553dd79ec 74 pc.printf("Unable to create the file '%s'\r\n", file_name);
ym1784 0:de9553dd79ec 75 pc.printf("Please try again\r\n");
ym1784 0:de9553dd79ec 76
ym1784 0:de9553dd79ec 77 User_Led1 = LED_OFF;
ym1784 0:de9553dd79ec 78 file_open = 0;
ym1784 0:de9553dd79ec 79 } else {
ym1784 0:de9553dd79ec 80 User_Led1 = LED_ON;
ym1784 0:de9553dd79ec 81 file_open = 1;
ym1784 0:de9553dd79ec 82 }
ym1784 0:de9553dd79ec 83
ym1784 0:de9553dd79ec 84 timer.stop();
ym1784 0:de9553dd79ec 85 timer.reset();
ym1784 0:de9553dd79ec 86 timer.start();
ym1784 0:de9553dd79ec 87 can2.attach(&can_check);
ym1784 0:de9553dd79ec 88
ym1784 0:de9553dd79ec 89 int tmptail;
ym1784 0:de9553dd79ec 90 while(1) {
ym1784 0:de9553dd79ec 91 if ( head != tail ) {
ym1784 0:de9553dd79ec 92 tmptail = (tail + 1) & BUFFER_MASK;
ym1784 0:de9553dd79ec 93 fprintf(fp, "%03X,%03X,", head&0xfff, tmptail&0xfff);
ym1784 0:de9553dd79ec 94 fprintf(fp, "%08X,", second[tmptail]);
ym1784 0:de9553dd79ec 95 fprintf(fp, "t%03X%d", can_id[tmptail], msg_length[tmptail]);
ym1784 0:de9553dd79ec 96
ym1784 0:de9553dd79ec 97 for (int i=0; i<msg_length[tmptail]; i++) {
ym1784 0:de9553dd79ec 98 fprintf(fp, "%02X", data[i][tmptail]);
ym1784 0:de9553dd79ec 99 } // for
ym1784 0:de9553dd79ec 100 fprintf(fp, "\r\n");
ym1784 0:de9553dd79ec 101
ym1784 0:de9553dd79ec 102 tail = tmptail; // update tail after data sent
ym1784 0:de9553dd79ec 103 if ( tail == 0 ) {
ym1784 0:de9553dd79ec 104 // toggle led3
ym1784 0:de9553dd79ec 105 User_Led3 = !User_Led3;
ym1784 0:de9553dd79ec 106 t = time( NULL ) + 32400; // UTC + 9 hours for JST
ym1784 0:de9553dd79ec 107 strftime( file_name, 20, "%T", localtime( &t ) );
ym1784 0:de9553dd79ec 108 pc.printf("new cycle of ring buffer at %s\r\n", file_name);
ym1784 0:de9553dd79ec 109 }
ym1784 0:de9553dd79ec 110 } // if head != tail
ym1784 0:de9553dd79ec 111
ym1784 0:de9553dd79ec 112 if ( BUTTON&0x01 ) { // button1 pressed
ym1784 0:de9553dd79ec 113 BUTTON &= 0xfe; // clear button status
ym1784 0:de9553dd79ec 114 can2.attach(0); // detach CAN interrupt
ym1784 0:de9553dd79ec 115 file_open = 0;
ym1784 0:de9553dd79ec 116 //Close the file
ym1784 0:de9553dd79ec 117 fclose(fp);
ym1784 0:de9553dd79ec 118 pc.printf("file closed\r\n");
ym1784 0:de9553dd79ec 119 User_Led1 = LED_OFF;
ym1784 0:de9553dd79ec 120 } // if button
ym1784 0:de9553dd79ec 121 } // while
ym1784 0:de9553dd79ec 122 } // main
ym1784 0:de9553dd79ec 123
ym1784 0:de9553dd79ec 124 // read CAN2 message using intterupt and ring buffer
ym1784 0:de9553dd79ec 125 void can_check(void) {
ym1784 0:de9553dd79ec 126 int temp_head;
ym1784 0:de9553dd79ec 127 if ( file_open == 1 ) {
ym1784 0:de9553dd79ec 128 while ( can2.read(can_MsgRx) ) {
ym1784 0:de9553dd79ec 129 temp_head = (head + 1) & BUFFER_MASK;
ym1784 0:de9553dd79ec 130 if ( temp_head == tail ) { // buffer overflow error
ym1784 0:de9553dd79ec 131 fclose(fp);
ym1784 0:de9553dd79ec 132 fprintf(stderr, "buffer overflow\r\n");
ym1784 0:de9553dd79ec 133 fprintf(stderr, "head = %d\r\n", head);
ym1784 0:de9553dd79ec 134 fprintf(stderr, "tail = %d\r\n", tail);
ym1784 0:de9553dd79ec 135 User_Led4 = 1;
ym1784 0:de9553dd79ec 136 exit(1);
ym1784 0:de9553dd79ec 137 } // if
ym1784 0:de9553dd79ec 138
ym1784 0:de9553dd79ec 139 second[temp_head] = timer.read_us();
ym1784 0:de9553dd79ec 140 can_id[temp_head] = can_MsgRx.id & 0xFFF;
ym1784 0:de9553dd79ec 141 msg_length[temp_head] = can_MsgRx.len;
ym1784 0:de9553dd79ec 142 for (int i=0; i<can_MsgRx.len; i++) {
ym1784 0:de9553dd79ec 143 data[i][temp_head] = can_MsgRx.data[i];
ym1784 0:de9553dd79ec 144 } // for
ym1784 0:de9553dd79ec 145 head = temp_head; // update head after data stored
ym1784 0:de9553dd79ec 146 // toggle led2
ym1784 0:de9553dd79ec 147 User_Led2 = !User_Led2;
ym1784 0:de9553dd79ec 148 } // while
ym1784 0:de9553dd79ec 149 } // if open
ym1784 0:de9553dd79ec 150 } // can_check
ym1784 0:de9553dd79ec 151
ym1784 0:de9553dd79ec 152 // read switch status, called every 5 msec
ym1784 0:de9553dd79ec 153 void check_sw() {
ym1784 0:de9553dd79ec 154 SW2 = SW1; // shift previous status
ym1784 0:de9553dd79ec 155 SW1 = SW0; // shift previous status
ym1784 0:de9553dd79ec 156 // get new status
ym1784 0:de9553dd79ec 157 SW0 = button1.read()+(button2.read()<<1)+(button3.read()<<2)+(button4.read()<<3);
ym1784 0:de9553dd79ec 158 // following sequence detects switch press edge
ym1784 0:de9553dd79ec 159 // HIGH(SW2) -> LOW(SW1) -> LOW(SW0)
ym1784 0:de9553dd79ec 160 BUTTON |= ((~(SW0|SW1))&SW2); // update button status
ym1784 0:de9553dd79ec 161 } // check_sw