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 Jim Carver

Revision:
7:169254b6eaf6
Parent:
6:02bfeec82bc1
--- 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