4 years, 8 months ago.

CSV , Array ,Mbed

Hi all

I am Chong . I am very bad and new to programming an mbed , currently facing some problems and hope that you may assist me .

I have successfully created a program that can read3axis of a accelerator (kxm 52-1050) . The teacher has asked me to save it in an array form but after much research , I am still unsure of how to use an array but managed to get the output file in txt format that displays 5 results without using array.(Picture below Current Output)

My current task is to carry on using the same measured data and save it as a CSV file and open it in Excel and draw a graph. (X axis as time and Y axis as acceleration of each [XYZ] axis of the accelerator )(Picture Below Graph Sample)

I was advised that I might still need to use an array if I change the sampling frequency faster as the processing time for using an array is faster and the format I am currently using may not support .

Therefore I am still stuck with : 1) Creating / Storing / Reading / Writing Arrays 2) Saving / Opening a CSV file

Hope you can assist me with these problems .

Here is my current code that works (It displays the values on both the LCD and Tera Term) :

  1. include "mbed.h"
  2. include "TextLCD.h" LocalFileSystem local("local"); TextLCD lcd(p24,p26,p27,p28,p29,p30); Serial pc(USBTX,USBRX); Ticker in; AnalogIn x_in(p17); AnalogIn y_in(p18); AnalogIn z_in(p19);

void update() { float x,y,z; x=x_in; y=y_in; z=z_in; lcd.cls(); lcd.locate(0,0); lcd.printf("X %5.2f",x); lcd.printf(" Y %5.2f",y); lcd.printf(" Z %5.2f",z); if(x<0.38) { lcd.printf("Stand"); } else if(x>0.38&&z<0.35) { lcd.printf("Fall"); } if(x>0.40&&0.40>z<0.62) { lcd.printf("Sleep"); } if(y<0.47) { lcd.printf("BK L"); } else if(y>0.53) { lcd.printf("BK R"); FILE *fp = fopen("/local/Record.txt", "w"); for(int i=0;i<5;i++){ fprintf(fp, "X- %f Y-%f Z-%f \r\n",x_in.read(),y_in.read(),z_in.read()); pc.printf("X-%5.2f Y-%5.2f Z-%5.2f \n",x, y, z); } fclose(fp); } } int main() {in.attach(&update,0.5);}

/* END OF CODE*/

Thank you all for your time :)

Please use <<code>> and <</code>> when posting code so that it formats correctly.

#include "mbed.h"
#include "TextLCD.h"

LocalFileSystem local("local");
TextLCD lcd(p24,p26,p27,p28,p29,p30);
Serial pc(USBTX,USBRX);
Ticker in;
AnalogIn x_in(p17);
AnalogIn y_in(p18);
AnalogIn z_in(p19);

void update() {
 float x,y,z;
 x=x_in;
 y=y_in;
 z=z_in;
 lcd.cls();
 lcd.locate(0,0);
 lcd.printf("X %5.2f",x);
 lcd.printf(" Y %5.2f",y);
 lcd.printf(" Z %5.2f",z);
 if(x<0.38) { 
    lcd.printf("Stand");
 } else if(x>0.38&&z<0.35) { 
  lcd.printf("Fall");
  }

 if(x>0.40&&0.40>z<0.62) { 
  lcd.printf("Sleep");
  }
 if(y<0.47) {
   lcd.printf("BK L");
  } else if(y>0.53) { 
   lcd.printf("BK R");
   FILE *fp = fopen("/local/Record.txt", "w");
     for(int i=0;i<5;i++) {
       fprintf(fp, "X- %f Y-%f Z-%f \r\n",x_in.read(),y_in.read(),z_in.read());
       pc.printf("X-%5.2f Y-%5.2f Z-%5.2f \n",x, y, z);
     }
     fclose(fp);
 }
 }

int main() {
  in.attach(&update,0.5);
}
posted by Andy A 17 Oct 2016

1 Answer

4 years, 8 months ago.

Saving it as an array is fairly easy, you do however have to add a check to make sure you haven't run out of space in your array:

const int maxReadings = 100;

float measurmentArray[maxReadings][3];

volatile int readingNumber = 0; // volatile because it's changed in an interrupt

void update() {
 if (readingNumber < maxReadings) {
   measurmentArray[readingNumber][0]=x_in;
   measurmentArray[readingNumber][1]=y_in;
   measurmentArray[readingNumber][2]=z_in;
   readingNumber++;
  }
.....

In your current code you have two potential problems with your file output. Firstly you open it with an access type of "w", that should overwrite any existing files so you'll only have a single point in the file. You should open it with an access type of "a" to append to the existing file. Secondly you never check that the file did open. You should verify that fp is not NULL before tying to use it.

You get 5 values in your file because within your timer you take 6 readings from the sensor, one set for setting the LCD and printing to the serial port 5 times and 5 other sets of data taken as quickly as possible for writing to the file. So the 5 values in your file aren't taken at the sample rate you set, they are taken at some unknown rate determined by the ADC sample time and the file write speed.

As a more general style point you are currently doing everything inside an interrupt, that is not normally a good idea, What you should do is read the values in the interrupt but do everything else in the main loop. e.g.

void update() {
[as above]
}

main () {
  int nextReading = 0;
  in.attach(&update,0.5);
  while (nextReading<maxReadings ) { // run until the array is full
    If (readingNumber > nextReading) { // there is new data
       nextReading = readingNumber-1; // the index of the last value written to the array
       float x,y,z;  // copy values to a local variables to save me doing a search and replace on the code below...
       x=measurmentArray[nextReading][0];
       y=measurmentArray[nextReading][1];
       z=measurmentArray[nextReading][2];
       lcd.cls();
       lcd.locate(0,0);
       lcd.printf("X %5.2f",x);
       lcd.printf(" Y %5.2f",y);
       lcd.printf(" Z %5.2f",y);
       if(x<0.38) { 
         lcd.printf("Stand");
       } else if(x>0.38&&z<0.35) { 
         lcd.printf("Fall");
       }
 
       if(x>0.40&&0.40>z<0.62) { 
         lcd.printf("Sleep");
       }
       if(y<0.47) {
         lcd.printf("BK L");
       } else if(y>0.53) { 
         lcd.printf("BK R");
       }

      pc.printf("X-%5.2f Y-%5.2f Z-%5.2f \n",x, y, z);
      nextReading++;
    } // end while new data to display
  }  // end while the array isn't full.
  
  // now write the whole array to a file in one go
 FILE *fp = fopen("/local/Record.txt", "w");
 if (fp) {
   for (int i=0;i<maxReadings;i++) {
       fprintf(fp, "X- %f Y-%f Z-%f \r\n",measurmentArray[i][0],measurmentArray[i][1],measurmentArray[i][2]);
    }
    fclose(fp);
  } else {
    pc.printf("ERROR. Failed to open output file\r\n");
  }
}

The downside in this array based system is that you can only read as much data as the array can hold but with your current system if you turned the sample rate up the whole thing would fall apart, you wouldn't know how fast it was running. This way the system will always keep up and run at the requested rate, if the screen update code can't keep up with the sample rate then it will skip samples and only ever display the most recent data.

Once the array is full the entire array is written to a text file in one go.

There are ways to make this sort of system run continuously. You use the array as a buffer, the ticker writes data into the array looping back to the start when it gets to the end. The main loop follows as closely behind as it can. This is useful because the time taken to write to a file varies, normally it's quite fast but sometimes it can take a long time. By using an array as a circular buffer if the the file writing takes a long time every now and then the sample rate isn't messed up, the buffer is in effect averaging out the file write times.

Accepted Answer

Thank you so much for your help , I will learn from my mistakes.

Really appreciate the help you have provided. Have a great day ahead

posted by Sze Ming Chong 18 Oct 2016