A data logger for the FRDM-K64F taking readings from the FXOS8700CQ accelerometer/magnometer at 200Hz.
Dependencies: FXOS8700CQ SDFileSystem mbed
Fork of Hello_FXOS8700Q by
Diff: main.cpp
- Revision:
- 7:169254b6eaf6
- Parent:
- 6:02bfeec82bc1
diff -r 02bfeec82bc1 -r 169254b6eaf6 main.cpp --- a/main.cpp Fri Apr 25 16:47:00 2014 +0000 +++ b/main.cpp Fri May 30 21:02:54 2014 +0000 @@ -1,53 +1,209 @@ #include "mbed.h" -#include "FXOS8700Q.h" +#include "FXOS8700CQ.h" +#include "SDFileSystem.h" + +#define DATA_RECORD_TIME_MS 20000 + +Serial pc(USBTX, USBRX); // for diagnostic output, beware blocking on long text +// Pin names for FRDM-K64F +SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); // MOSI, MISO, SCLK, SSEL, "name" +FXOS8700CQ fxos(PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // SDA, SCL, (addr << 1) + +DigitalOut green(LED_GREEN); +DigitalOut blue(LED_BLUE); +DigitalOut red(LED_RED); + +Timer t; // Microsecond timer, 32 bit int, maximum count of ~30 minutes +InterruptIn fxos_int1(PTC6); +InterruptIn fxos_int2(PTC13); +InterruptIn start_sw(PTA4); // switch SW3 -//FXOS8700Q acc( A4, A5, FXOS8700CQ_SLAVE_ADDR0); // Proper Ports and I2C address for Freescale Multi Axis shield -//FXOS8700Q mag( A4, A5, FXOS8700CQ_SLAVE_ADDR0); // Proper Ports and I2C address for Freescale Multi Axis shield -FXOS8700Q_acc acc( PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // Proper Ports and I2C Address for K64F Freedom board -FXOS8700Q_mag mag( PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // Proper Ports and I2C Address for K64F Freedom board +bool fxos_int1_triggered = false; +bool fxos_int2_triggered = false; +uint32_t us_ellapsed = 0; +bool start_sw_triggered = false; + +uint32_t sample_count = 0; + +SRAWDATA accel_data; +SRAWDATA magn_data; + +char sd_buffer[BUFSIZ * 2]; // create an appropriately sized buffer + +void trigger_fxos_int1(void) +{ + fxos_int1_triggered = true; +} + +void trigger_fxos_int2(void) +{ + fxos_int2_triggered = true; + us_ellapsed = t.read_us(); +} -Serial pc(USBTX, USBRX); +void trigger_start_sw(void) +{ + start_sw_triggered = true; +} + +void print_reading(void) +{ + pc.printf("A X:%5d,Y:%5d,Z:%5d M X:%5d,Y:%5d,Z:%5d\r\n", + accel_data.x, accel_data.y, accel_data.z, + magn_data.x, magn_data.y, magn_data.z); +} + +void write_reading(FILE* fp) +{ + fprintf(fp, "%d, %d,%d,%d, %d,%d,%d\r\n", + us_ellapsed, + accel_data.x, accel_data.y, accel_data.z, + magn_data.x, magn_data.y, magn_data.z); +} -MotionSensorDataUnits mag_data; -MotionSensorDataUnits acc_data; +void write_csv_header(FILE* fp) +{ + fprintf(fp, "timestamp, acc-x, acc-y, acc-z, magn-x, magn-y, magn-z, scale: %d\r\n", + fxos.get_accel_scale()); +} -MotionSensorDataCounts mag_raw; -MotionSensorDataCounts acc_raw; +/* + * Writing binary to the file: + * Timestamp: uint32_t written B0 B1 B2 B3 + * Raw data: int16_t written B0 B1 + * Packed resulting format, 16 bytes: + * TS0 TS1 TS2 TS3 AX0 AX1 AY0 AY1 AZ0 AZ1 MX0 MX1 MY0 MY1 MZ0 MZ1 + */ +void write_binary(FILE* fp) +{ + uint8_t out_buffer[16] = { + (uint8_t)(us_ellapsed), (uint8_t)(us_ellapsed >> 8), + (uint8_t)(us_ellapsed >> 16), (uint8_t)(us_ellapsed >> 24), + (uint8_t)(accel_data.x), (uint8_t)(accel_data.x >> 8), + (uint8_t)(accel_data.y), (uint8_t)(accel_data.y >> 8), + (uint8_t)(accel_data.z), (uint8_t)(accel_data.z >> 8), + + (uint8_t)(magn_data.x), (uint8_t)(magn_data.x >> 8), + (uint8_t)(magn_data.y), (uint8_t)(magn_data.y >> 8), + (uint8_t)(magn_data.z), (uint8_t)(magn_data.z >> 8) + }; + + fwrite( (const uint8_t*) out_buffer, sizeof(uint8_t), 16, fp); +} -int main() { -float faX, faY, faZ; -float fmX, fmY, fmZ; -int16_t raX, raY, raZ; -int16_t rmX, rmY, rmZ; -acc.enable(); -printf("\r\n\nFXOS8700Q Who Am I= %X\r\n", acc.whoAmI()); - while (true) { - acc.getAxis(acc_data); - mag.getAxis(mag_data); - printf("FXOS8700Q ACC: X=%1.4f Y=%1.4f Z=%1.4f ", acc_data.x, acc_data.y, acc_data.z); - printf(" MAG: X=%4.1f Y=%4.1f Z=%4.1f\r\n", mag_data.x, mag_data.y, mag_data.z); - acc.getX(&faX); - acc.getY(&faY); - acc.getZ(&faZ); - mag.getX(&fmX); - mag.getY(&fmY); - mag.getZ(&fmZ); - printf("FXOS8700Q ACC: X=%1.4f Y=%1.4f Z=%1.4f ", faX, faY, faZ); - printf(" MAG: X=%4.1f Y=%4.1f Z=%4.1f\r\n", fmX, fmY, fmZ); - acc.getAxis(acc_raw); - mag.getAxis(mag_raw); - printf("FXOS8700Q ACC: X=%d Y=%d Z=%d ", acc_raw.x, acc_raw.y, acc_raw.z); - printf(" MAG: X=%d Y=%d Z=%d\r\n", mag_raw.x, mag_raw.y, mag_raw.z); - acc.getX(&raX); - acc.getY(&raY); - acc.getZ(&raZ); - mag.getX(&rmX); - mag.getY(&rmY); - mag.getZ(&rmZ); - printf("FXOS8700Q ACC: X=%d Y=%d Z=%d ", raX, raY, raZ); - printf(" MAG: X=%d Y=%d Z=%d\r\n\n", rmX, rmY, rmZ); +void read_binary(FILE* fp) +{ + uint8_t in_buffer[16]; + fread( in_buffer, sizeof(uint8_t), 16, fp); + us_ellapsed = (in_buffer[0]) | (in_buffer[1] << 8)| + (in_buffer[2] << 16) | (in_buffer[3] << 24); + + accel_data.x = in_buffer[4] | (in_buffer[5] << 8); + accel_data.y = in_buffer[6] | (in_buffer[7] << 8); + accel_data.z = in_buffer[8] | (in_buffer[9] << 8); + + magn_data.x = in_buffer[10] | (in_buffer[11] << 8); + magn_data.y = in_buffer[12] | (in_buffer[13] << 8); + magn_data.z = in_buffer[14] | (in_buffer[15] << 8); +} + +int main(void) +{ + // Setup + t.reset(); + pc.baud(115200); // Move pc.printf's right along + green.write(1); // lights off + red.write(1); + blue.write(1); + + pc.printf("\r\nTime to start setup!\r\n"); + + // Prepare file stream for saving data + FILE* fp_raw = fopen("/sd/data.bin", "w"); + + if(0 == setvbuf(fp_raw, &sd_buffer[0], _IOFBF, BUFSIZ)) { + pc.printf("Buffering \"/sd/\" with %d bytes.\r\n", BUFSIZ); + } else { + pc.printf("Failed to buffer SD card with %d bytes.\r\n", BUFSIZ); + } + + // Iterrupt for active-low interrupt line from FXOS + fxos_int2.fall(&trigger_fxos_int2); + fxos.enable(); // enable our device, configured in constructor + + // Interrupt for active-high trigger + start_sw.mode(PullUp); // Since the FRDM-K64F doesn't have its SW2/SW3 pull-ups populated + start_sw.fall(&trigger_start_sw); + green.write(0); // light up ready-green + + // Example data printing + fxos.get_data(&accel_data, &magn_data); + print_reading(); + + pc.printf("Waiting for timed data collection trigger on SW3\r\n"); + + while(true) { + if(start_sw_triggered) { + start_sw_triggered = false; + break; // Received start button press + } + wait_ms(50); // short wait will have little effect on UX + } + + green.write(1); // ready-green off + blue.write(0); // working-blue on + + pc.printf("Started data collection\r\n"); + + sample_count = 0; + fxos.get_data(&accel_data, &magn_data); // clear interrupt from device + fxos_int2_triggered = false; // un-trigger + + t.start(); // start timer and enter collection loop + while (t.read_ms() <= DATA_RECORD_TIME_MS) { + if(fxos_int2_triggered) { + fxos_int2_triggered = false; // un-trigger + fxos.get_data(&accel_data, &magn_data); + // pc.printf("S: %d\r\n", us_ellapsed); // complex status printout + pc.putc('.'); // show that a sample was taken + write_binary(fp_raw); // needs to take <5ms to avoid blocking next transfer + ++sample_count; // successfully sampled and wrote! + } + } + + red.write(0); // red on, display purple for file reprocessing + + pc.printf("Done collecting. Reprocessing data to CSV.\r\n"); + fflush(fp_raw); + fclose(fp_raw); + + // Reopen the binary data as read, open CSV for write + fp_raw = fopen("/sd/data.bin", "r"); + FILE* fp_csv = fopen("/sd/data.csv", "w"); + + write_csv_header(fp_csv); // write out CSV header + + // Split the buffer between the two + setvbuf(fp_csv, &sd_buffer[0], _IOFBF, BUFSIZ); + setvbuf(fp_raw, &sd_buffer[BUFSIZ], _IOFBF, BUFSIZ); + + for(uint32_t i = sample_count; i > 0; --i) { + read_binary(fp_raw); + write_reading(fp_csv); + } + + fclose(fp_csv); + fclose(fp_raw); + + pc.printf("Done processing. Wrote binary into CSV."); + + red.write(1); // red off, green on, display yellow for done + green.write(0); + + while(true) { + pc.putc('.'); wait(1.0); } } \ No newline at end of file