
Data Logger Mangue Baja
Diff: main.cpp
- Revision:
- 0:aef6b59caed0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Jul 05 00:02:13 2019 +0000 @@ -0,0 +1,256 @@ +/* + Data Logger implementation in K64F. + Inputs: + x6 Analog Inputs; + x2 Digital (Frequency) Inputs; + x1 Internal Accelerometer (FXOS8700); + x1 External Accelerometer and Gyroscope (LSM6DS3); + In this set, it is designed for a 200Hz sample rate. + All the data are saved periodically (every 0.25s) to a folder in the SD card. + To read the data, use the file "read_struct.c" in the folder results. + + Implemented by Diego "sid" Hamilton, Electronics Coordinator at Mangue Baja Team, UFPE. +*/ + +#include "mbed.h" +#include "LSM6DS3.h" +#include "FXOS8700CQ.h" +#include "SDFileSystem.h" +#include <cstdlib> + +#define SERIAL_BAUD 1000000 // Board baud rate +#define BUFFER_SIZE 200 // Acquisition buffer +#define SAVE_WHEN 50 // Number of packets to save (fail safe) +#define SAMPLE_FREQ 200 // Frequency in Hz + +/* Debug */ +PwmOut signal_wave(D3); // Debug wave to test frequency channels +/* I/O */ +Serial pc(USBTX, USBRX, SERIAL_BAUD); // Debug purposes +SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); // MOSI, MISO, SCK, CS +//DigitalOut warning(D3); // When device is ready, led is permanently OFF +//DigitalOut logging(D4); // When data is beign acquired, led is ON +InterruptIn start(D2, PullUp); // Press button to start/stop acquisition +InterruptIn freq_chan1(D0, PullUp); // Frequency channel 1 +InterruptIn freq_chan2(D1, PullUp); // Frequency channel 2 +AnalogIn pot0(A0), + pot1(A1), + pot2(A2), + pot3(A3), + pot4(A4), + pot5(A5); +LSM6DS3 LSM6DS3(PTE25,PTE24); // External accelerometer and gyroscope +FXOS8700CQ fxos(PTE25,PTE24); // Internal accelerometer (and magnetometer, not used) + +//Ajuste para usar o led da placa +DigitalOut logging(LED1); +DigitalOut warning(LED2); +//DigitalOut led3(LED3); + +/* Data structure */ +typedef struct +{ + int16_t acclsmx; + int16_t acclsmy; + int16_t acclsmz; + int16_t anglsmx; + int16_t anglsmy; + int16_t anglsmz; + int16_t accfxox; + int16_t accfxoy; + int16_t accfxoz; + uint16_t analog0; + uint16_t analog1; + uint16_t analog2; + uint16_t analog3; + uint16_t analog4; + uint16_t analog5; + uint16_t pulses_chan1; + uint16_t pulses_chan2; + uint32_t time_stamp; +} packet_t; + +Timer t; // Device timer +Ticker acq; // Acquisition timer interrupt source +CircularBuffer<packet_t, BUFFER_SIZE> buffer; // Acquisition buffer +int buffer_counter = 0; // Packet currently in buffer +bool running = false; // Device status +//bool running = true; // Einstein's Adaptation +uint16_t pulse_counter1 = 0, + pulse_counter2 = 0; // Frequency counter variables +uint16_t acc_addr = 0; /* LSM6DS3 address, if not connected + address is 0 and data is not stored */ + +void sampleISR(); // Data acquisition ISR +uint32_t count_files_in_sd(const char *fsrc); // Compute number of files in SD +void freq_channel1_ISR(); // Frequency counter ISR, channel 1 +void freq_channel2_ISR(); // Frequency counter ISR, channel 2 +void toggle_logging(); // Start button ISR + +int main() +{ + uint32_t t1,t2; + logging = 0; // logging led OFF + int num_parts = 0, // Number of parts already saved + num_files = 0, // Number of files in SD + svd_pck = 0; // Number of saved packets (in current part) + char name_dir[12]; // Name of current folder (new RUN) + char name_file[20]; // Name of current file (partX) + FILE* fp; + packet_t temp; + packet_t trash; + signal_wave.period_ms(50); + signal_wave.write(0.5f); + + /* Initialize accelerometers */ + acc_addr = LSM6DS3.begin(LSM6DS3.G_SCALE_245DPS, LSM6DS3.A_SCALE_2G, \ + LSM6DS3.G_ODR_208, LSM6DS3.A_ODR_208); + fxos.init(); + + /* Wait for SD ready */ + while(sd.disk_status()) + { + sd.disk_initialize(); + warning = 0; + wait(1.0); + warning = 1; + wait(1.0); + } + + num_files = count_files_in_sd("/sd"); + sprintf(name_dir, "%s%d", "/sd/RUN", num_files + 1); + + start.fall(&toggle_logging); // Attach start button ISR + while(!running) // Wait button press + warning = 1; // For some reason if this line is empty the code doesn't run + + /* Create RUN directory */ + mkdir(name_dir, 0777); + warning = 0; + sprintf(name_file, "%s%s%d", name_dir, "/part", num_parts++); + fp = fopen(name_file, "w"); // Creates first data file + t.start(); // Start device timer + freq_chan1.fall(&freq_channel1_ISR); + freq_chan2.fall(&freq_channel2_ISR); + acq.attach(&sampleISR, 1.0/SAMPLE_FREQ); // Start data acquisition + logging = 1; + // logging led ON + + while(running) + { + + if(buffer.full()) + { + warning = 1; // Turn warning led ON if buffer gets full (abnormal situation) + //pc.putc('X'); // Debug message + //buffer.pop(trash); + } + else if(!buffer.empty()) + { + //pc.putc('G'); // Debug message + /* Remove packet from buffer and writes it to file */ + buffer.pop(temp); + buffer_counter--; + //t1 = t.read_ms(); + fwrite((void *)&temp, sizeof(packet_t), 1, fp); + //t2 = t.read_ms()-t1; + //pc.printf("%d\r\n",t2); + svd_pck++; + /* Create new data file */ + if(svd_pck == SAVE_WHEN) + { + fclose(fp); + sprintf(name_file, "%s%s%d", name_dir, "/part", num_parts++); + fp = fopen(name_file, "w"); + //pc.printf("%d\n", buffer_counter); // Debug message + svd_pck = 0; + + } + } + /* Software debounce for start button */ + if((t.read_ms() > 10) && (t.read_ms() < 20)) + start.fall(toggle_logging); + } + + /* Reset device if start button is pressed while logging */ + logging = 0; + NVIC_SystemReset(); + return 0; +} + +void sampleISR() +{ + static uint16_t last_acq = t.read_ms(); // Time of last acquisition + packet_t acq_pck; // Current data packet + Data fxos_acc; + fxos_acc = fxos.get_values(); // Read FXOS8700 data + /* Store LSM6DS3 data if it's connected */ + if (acc_addr != 0) + { + LSM6DS3.readAccel(); // Read Accelerometer data + LSM6DS3.readGyro(); // Read Gyroscope data + + acq_pck.acclsmx = LSM6DS3.ax_raw; + acq_pck.acclsmy = LSM6DS3.ay_raw; + acq_pck.acclsmz = LSM6DS3.az_raw; + acq_pck.anglsmx = LSM6DS3.gx_raw; + acq_pck.anglsmy = LSM6DS3.gy_raw; + acq_pck.anglsmz = LSM6DS3.gz_raw; + } + else + { + acq_pck.acclsmx = 0; + acq_pck.acclsmy = 0; + acq_pck.acclsmz = 0; + acq_pck.anglsmx = 0; + acq_pck.anglsmy = 0; + acq_pck.anglsmz = 0; + } + acq_pck.accfxox = fxos_acc.ax; + acq_pck.accfxoy = fxos_acc.ay; + acq_pck.accfxoz = fxos_acc.az; + acq_pck.analog0 = pot0.read_u16(); // Read analog sensor 0 + acq_pck.analog1 = pot1.read_u16(); // Read analog sensor 1 + acq_pck.analog2 = pot2.read_u16(); // Read analog sensor 2 + acq_pck.analog3 = pot3.read_u16(); // Read analog sensor 3 + acq_pck.analog4 = pot4.read_u16(); // Read analog sensor 4 + acq_pck.analog5 = pot5.read_u16(); // Read analog sensor 5 + acq_pck.pulses_chan1 = pulse_counter1; // Store frequence channel 1 + acq_pck.pulses_chan2 = pulse_counter2; // Store frequence channel 2 + acq_pck.time_stamp = t.read_ms(); // Timestamp of data acquistion + + pulse_counter1= 0; + pulse_counter2= 0; + buffer.push(acq_pck); + buffer_counter++; +} + +uint32_t count_files_in_sd(const char *fsrc) +{ + DIR *d = opendir(fsrc); + struct dirent *p; + uint32_t counter = 0; + + while ((p = readdir(d)) != NULL) { + if(strcmp(p->d_name, ".Trash-1000")) + counter++; + } + closedir(d); + return counter; +} + +void freq_channel1_ISR() +{ + pulse_counter1++; +} + +void freq_channel2_ISR() +{ + pulse_counter2++; +} + +void toggle_logging() +{ + running = !running; + start.fall(NULL); +}