8 years, 7 months ago.

How to store maximum samples per second?

For my data logging project , I need to store maximum samples per second. I'm working with 3-axis accelerometer and Nucleo-L053R8 board.

Should i use any special functions?? or??

Question relating to:

2 Answers

8 years, 7 months ago.

How fast is the maximum?

I've logged 1kHz gyro and accelerometer data using an LPC1768, you have less CPU power on hand but a lot of the time is spent waiting for the card which isn't going to be any slower for you.

There are a few key tricks to use:

Don't open and close the file between writes, keep it open. This means pulling the card out will result in data loss so ensure you either have a stop button or only write a certain amount to each file and then close it and create a new one. I will have a file index that starts at 0, after writing a certain number of bytes I finish the current write, close the file, increase the index and open a new file. That way if the power goes out, the program crashes or the card is removed I only lose the last 30-40 seconds worth of data, A single command line on the PC afterwards (cat log*.txt > all.txt) will combine them all back into a single file if needed.

Write data in blocks, have an interrupt routine to read the sensor and put the data in a buffer. Once the buffer is full switch to a new buffer and have the background loop write the old buffer to the card. By using pointers to the current buffer you can avoid slow if statements at every read and write. I've ended up with an array of 16 buffers like this before, if the card glitched I could end up queuing up 15 buffers worth of data to write before I started to lose information.

Go for the highest data density you can easily use in the save file. Text files may be nice to read but they take up a lot more space e.g. 10 bytes for a floating point number rather than 4 for the same number in binary. Whether the larger (and slower) files are worth it will depending on your use and what needs to read the logs.

No debug printfs, they are slow. Flash LEDs for debug/status information or if you need more use putc to output a single character to the terminal..

Accepted Answer

#include "ADXL345_I2C.h"
#include "mbed.h"
#include "SDFileSystem.h"


 ADXL345_I2C accelerometer(D14,D15);
 SDFileSystem sd(D11,D12,D13,PB_6, "sd"); // MOSI, MISO, SCLK, SSEL
 //DigitalOut myled(LED1);
 
 
 Serial pc(USBTX, USBRX);

 int main() {
       pc.baud(115200);
      // printf("RTC example\n"); 
       set_time(1387188323); // Set RTC time to 16 December 2013 10:05:23 UTC
      // printf("Date and time are set.\n");
     int readings[3] = {0, 0, 0};
     
     pc.printf("Starting ADXL345 test...\n");
     wait(.001);
     pc.printf("Device ID is: 0x%02x\n", accelerometer.getDeviceID());
    wait(.001);
    
     // These are here to test whether any of the initialization fails. It will print the failure
    if (accelerometer.setPowerControl(0x00)){
         pc.printf("didn't intitialize power control\n"); 
         return 0;  }
     //Full resolution, +/-16g, 4mg/LSB.
     wait(.001);
     
     if(accelerometer.setDataFormatControl(0x0B)){
        pc.printf("didn't set data format\n");
        return 0;  }
     wait(.001);
     
     //3.2kHz data rate.
     if(accelerometer.setDataRate(ADXL345_3200HZ)){
        pc.printf("didn't set data rate\n");
        return 0;    }
     wait(.001);
     
     //Measurement mode.
     
     if(accelerometer.setPowerControl(MeasurementMode)) {
        pc.printf("didn't set the power control to measurement\n"); 
        return 0;   } 
       
  
     while (1) {
     
         
         
         accelerometer.getOutput(readings);
         time_t seconds = time(NULL);

        char buffer[32];
        strftime(buffer, 32, "%I:%M:%S %p", localtime(&seconds));
        printf("          Time = %s", buffer);

       //myled = !myled;  
       //pc.printf("\r\n%i, %i, %i", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2]);
        FILE *fp = fopen("/sd/PCE datalog.txt", "a");      
       fprintf(fp,"\r\n Accelerometer: X: %ig, Y: %ig, Z: %ig", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2]);
       fprintf(fp,"       Time = %s", buffer);
          
       fclose(fp);    
        
        wait(0.001);
     }
 
 }

This is the my main code. I could able to store about 30 samples per second. SD card is working for only 5 seconds every time.

I'm planning to store a minimum of 60 samples.

posted by Mohan gandhi Vinnakota 31 Aug 2015

For the benefit of anyone finding this question when searching the final code was:

#include "mbed.h"
#include "ADXL345_I2C.h"
#include "SDFileSystem.h"
 
ADXL345_I2C accelerometer(D14,D15);
SDFileSystem sd(D11,D12,D13,PB_6, "sd"); // MOSI, MISO, SCLK, SSEL
 
Serial pc(USBTX, USBRX);
 
Ticker fileUpdate;
FILE *logFile = NULL;
 
 
void onFileUpdate(void)
{
    static int fileNumber = 0;
    if (logFile)
        fclose(logFile);
 
    char fileName[20];
    sprintf(fileName,"/sd/PCEdata%03d.txt",fileNumber++);
    logFile = fopen(fileName,"w");
    pc.putc('\n');
}
 
 
 
 
int main()
{
    pc.baud(115200);
    set_time(1387188323); // Set RTC time to 16 December 2013 10:05:23 UTC
    int readings[3] = {0, 0, 0};
 
    pc.printf("Starting ADXL345 test...\n");
    pc.printf("Device ID is: 0x%02x\n", accelerometer.getDeviceID());
    wait(.001);
 
    // These are here to test whether any of the initialization fails. It will print the failure
    if (accelerometer.setPowerControl(0x00)) {
        pc.printf("didn't intitialize power control\n");
        return 0;
    }
    //Full resolution, +/-16g, 4mg/LSB.
    wait(.001);
 
    if(accelerometer.setDataFormatControl(0x0B)) {
        pc.printf("didn't set data format\n");
        return 0;
    }
    wait(.001);
 
    //3.2kHz data rate.
    if(accelerometer.setDataRate(ADXL345_3200HZ)) {
        pc.printf("didn't set data rate\n");
        return 0;
    }
    wait(.001);
 
    //Measurement mode.
 
    if(accelerometer.setPowerControl(MeasurementMode)) {
        pc.printf("didn't set the power control to measurement\n");
        return 0;
    }
 
    onFileUpdate(); // open the first log file;
    fileUpdate.attach(onFileUpdate,60); // every minute switch to a new log file.
 
    char buffer[32];
    time_t seconds = time(NULL);
 
    while (1) {
 
        accelerometer.getOutput(readings);
 
        strftime(buffer, 32, "%I:%M:%S %p", localtime(&seconds));
 
        pc.putc('r'); // put a single character indicating we read data.
 
        fprintf(logFile,"\r\n Accelerometer: X: %ig, Y: %ig, Z: %ig", readings[0], readings[1], readings[2]);
        fprintf(logFile,"       Time = %s", buffer);
 
    }
 
}
posted by Andy A 02 Sep 2015
8 years, 7 months ago.

I would like to suggest you to use a ring buffer.
Please refer to my CAN message logging program ...
https://developer.mbed.org/users/ym1784/code/CAN_LOG_SD/