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

main.cpp

Committer:
trm
Date:
2014-05-30
Revision:
7:169254b6eaf6
Parent:
6:02bfeec82bc1

File content as of revision 7:169254b6eaf6:

#include "mbed.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

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();
}

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);
}

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());
}

/*
 * 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);
}

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);
    }
}