mangue baja 1st working logger on stm32
Dependencies: LSM6DS3 DebouncedInterrupt
main.cpp
- Committer:
- einsteingustavo
- Date:
- 2022-09-21
- Revision:
- 5:122b9fd3df1a
- Parent:
- 3:15d63b793f7b
File content as of revision 5:122b9fd3df1a:
/* Data Logger implementation in STM32F103C8T6. Inputs: 1x External Accelerometer and Gyroscope (LSM6DS3) x3 Analog Inputs; x2 Digital (Frequency) Inputs; 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_struct2.0.c" in the folder results. Implemented by Einstein "Hashtag" Gustavo(Electronics Coordinator 2019) at Mangue Baja Team, UFPE. */ #include "mbed.h" #include <stdio.h> #include <errno.h> #include "SDBlockDevice.h" #include "FATFileSystem.h" #include "LSM6DS3.h" #include "DebouncedInterrupt.h" #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(PB_3); // Debug wave to test frequency channels /* I/O */ Serial pc(PA_2, PA_3); // Debug purposes LSM6DS3 LSM6DS3(PB_9, PB_8); // Gyroscope/Accelerometer declaration (SDA,SCL) SDBlockDevice sd(PB_15, PB_14, PB_13, PB_12); // mosi, miso, sck, cs FATFileSystem fileSystem("sd"); DigitalOut warning(PA_15); // When device is ready, led is permanently OFF DigitalOut logging(PA_12); // When data is beign acquired, led is ON //InterruptIn start(PB_4,PullUp); // Press button to start/stop acquisition DebouncedInterrupt start(PB_4); InterruptIn freq_chan1(PB_5,PullUp); // Frequency channel 1 InterruptIn freq_chan2(PB_6,PullUp); // Frequency channel 2 AnalogIn pot0(PB_1), pot1(PB_0), pot2(PA_7); /* Data structure */ typedef struct { int16_t acclsmx; int16_t acclsmy; int16_t acclsmz; int16_t anglsmx; int16_t anglsmy; int16_t anglsmz; uint16_t analog0; uint16_t analog1; uint16_t analog2; 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 int err; // SD library utility bool running = false; // Device status bool StorageTrigger = false; uint16_t pulse_counter1 = 0, pulse_counter2 = 0, // Frequency counter variables 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() { pc.printf("\r\nDebug 1\r\n"); 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; signal_wave.period_us(50); signal_wave.write(0.5f); /* Initialize accelerometer */ acc_addr = LSM6DS3.begin(LSM6DS3.G_SCALE_245DPS, LSM6DS3.A_SCALE_2G, \ LSM6DS3.G_ODR_208, LSM6DS3.A_ODR_208); /* Wait for SD mount */ do { /* Try to mount the filesystem */ pc.printf("Mounting the filesystem... "); fflush(stdout); err = fileSystem.mount(&sd); pc.printf("%s\n", (err ? "Fail :(" : "OK")); if (err) { /* Reformat if we can't mount the filesystem this should only happen on the first boot */ pc.printf("No filesystem found, formatting... "); fflush(stdout); err = fileSystem.reformat(&sd); pc.printf("%s\n", (err ? "Fail :(" : "OK")); if (err) { error("error: %s (%d)\n", strerror(-err), err); } } }while(err); pc.printf("\r\nDebug 2\r\n"); pc.printf("\r\nDebug 3\r\n"); num_files = count_files_in_sd("/sd"); sprintf(name_dir, "%s%d", "/sd/RUN", num_files + 1); pc.printf("\r\nDebug 4\r\n"); pc.printf("\r\nNum_files = %d\r\n", num_files); //start.fall(&toggle_logging); // Attach start button ISR start.attach(&toggle_logging, IRQ_FALL, 500, true); while(!running) // Wait button press { warning = 1; pc.printf("\r\nrunning=%d\r\n", running); // For some reason if this line is empty the code doesn't run } /* Create RUN directory */ mkdir(name_dir, 0777); warning = 0; // Warning led OFF //sprintf(name_file, "%s%s%d", name_dir, "/part", num_parts++); sprintf(name_file, "%s%s%d", name_dir, "/part", num_parts+1); fp = fopen(name_file, "a"); // 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(StorageTrigger) { packet_t acq_pck; // Current data packet static uint16_t last_acq = t.read_ms(); // Time of last acquisition /* 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.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.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++; StorageTrigger = false; } if(buffer.full()) { fclose(fp); warning = 1; // Turn warning led ON if buffer gets full (abnormal situation) pc.putc('X'); // Debug message } else if(!buffer.empty()) { pc.putc('G'); // Debug message /* Remove packet from buffer and writes it to file */ buffer.pop(temp); buffer_counter--; fwrite((void *)&temp, sizeof(packet_t), 1, fp); svd_pck++; /* Create new data file (Deactivated because the code doesn't works fine doing that so many times) */ if(svd_pck == SAVE_WHEN) { //fclose(fp); //sprintf(name_file, "%s%s%d", name_dir, "/part", num_parts++); //t2 = t.read_ms(); //fp = fopen(name_file, "w"); //printf("t2=%d\r\n",(t.read_ms()-t2)); //pc.printf("%d\r\n", buffer_counter); // Debug message svd_pck = 0; } } /* Software debounce for start button if((t.read_ms() > 10) && (t.read_ms() < 1000)) { start.fall(toggle_logging); }*/ } /* Reset device if start button is pressed while logging */ fclose(fp); logging = 0; NVIC_SystemReset(); return 0; } void sampleISR() { StorageTrigger = true; } 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); }