Shop OBEX P1 Docs P2 Docs Learn Events
data logging — Parallax Forums

data logging

Boblow45Boblow45 Posts: 7
edited 2015-03-02 09:42 in Propeller 1
I am still new to the prop. I am trying to do some data logging with the prop and do some post processing in MatLab. The current code I have saves to binary. I want to know is there a way to save to an SD Card in ASCII. I have code that reads .CSV files in MatLab from old Arduino code I had for data logging. Any help would be great. Below is my current code
#include "simpletools.h"                      // Include simpletools header    


int MISO = 12;
int SCLK = 13;
int MOSI = 14;
int SS   = 15;
     
// SD card pins on Propeller BOE


// DO  = MISO
// DI  = MOSI
// CLK = SCLK
// CS  = SS


// red    wire is DO   :    pin 12 (MISO)
// black  wire is SCLK :    pin 13 (SCLK)
// yellow wire is DI   :    pin 14 (MOSI)
// green  wire is CS   :    pin 15 (SS)
 
  
int main(void)                                // main function
{
  
 char data [8] = {'2', '3' , '5', '7', '11', '13'};
 
 int mout = sd_mount (MISO, SCLK, MOSI, SS);
  




 print("%d \n", mout);  
  FILE* fp = fopen("test.txt", "w");          // Open a file for writing
  //fwrite("Hello World....", 1, 15, fp);     // Add contents to the file
  for (int i=0;i<3;i++)
  {
  fwrite(&data, 4, 8, fp);                 // Add contents to the file
  }  
  fclose(fp);                                 // Close the file
 
  char s[8];                                   // Buffer for characters
  fp = fopen("test.txt", "r");                // Reopen file for reading
  fread(&s, 4, 8, fp);                        // Read 15 characters
  fclose(fp);                                 // Close the file


  print("First 15 chars in test.txt:\n");     // Display heading
  print("%s", s);                             // Display characters
  print("\n");  
  pause(500);






while (1)
{ 


}


}  

Comments

  • ersmithersmith Posts: 6,053
    edited 2015-02-26 02:58
    Is your current code working? You said you could log to binary, so I'm not quite sure I understand the problem -- ASCII is just a particular kind of binary, after all. Are you looking for the fprintf() function to print numbers to a file as decimal or hexadecimal?
  • Boblow45Boblow45 Posts: 7
    edited 2015-02-26 13:04
    Yes the current data logger works. My MatLab code requires a .csv file in the following format ''A,12,13,4,G,34,23,12'' where the current code saves it as '' 002,003,002....'' in a binary format. I want to save it in the format of the old Arduino code. I might be doing something stupid. Any help is appreciated.
  • ersmithersmith Posts: 6,053
    edited 2015-02-26 16:53
    I don't know exactly what format you want to write in, but in general instead of doing an "fwrite" call in the code above you should use "fprintf". Something like:
    fprintf(f, "A,%d,%d,%d,G,%d,%d,%d\n", val1, val2, val3, val4, val5,val6);
    
    "fwrite" is generally used to write binary data, and "fprintf" does formatted printing of ASCII values. There's a whole lot of documentation on-line about fprintf (and printf; they both use the same format strings, and underneath are the same function). Basically fprintf will print the string to a file, replacing any special escapes (starting with %) with the values passed in. Use %d for decimal, %x for hex, %c for an ASCII character, and %s for a string. You can also specify exact widths for the things you print, and whether they should be padded with 0 or space; for example,
    fprintf(f, "A = %04d", 71);
    
    will put "A = 0071" in the file.
  • Boblow45Boblow45 Posts: 7
    edited 2015-02-27 11:40
    That answers my question perfectly. Thanks for the help.
  • Boblow45Boblow45 Posts: 7
    edited 2015-03-02 06:28
    I am wondering what is the smallest ''code sized function'' that can write to a SD card for logging data. I found fwrite to be the smallest. I am wondering as I have problems with fitting all my code onto a signal propeller chip. I know one can do a master slave config, but if I could reduce the code down so all the code fits it would be better. It doesn't matter what it saves the data as long as one can convert it to something understandable like an int. any help would be great
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-03-02 08:20
    It is probably worth giving the SD class in libpropeller a shot. I can't promise it's smaller - might be exactly the same, or larger - but I can promise it's different from PropGCC's built-in SD functions.

    fwrite is going to be smaller than fprintf - but as you noticed, it needs a little bit of help to put the data in a more meaningful format. My suggestion: if you're trying to get every last byte of RAM back, then write your own function to convert integers to strings then log the data with repeated calls to fwrite. If the only format character you ever use is %d, then fprintf is going to pull in a lot more than you need.

    PropWare's Printer class could help you with this actually. Instructions for using PropWare's Printer class follow:

    Create a file named sdprinter.h with the following contents:
    #include <PropWare/printcapable.h> // You may want to change this include to be the path that printcapable.h is in
    #include <stdio.h>
    #include <string.h>
    
    class SDWriter : public PropWare::PrintCapable {
        public:
            SDWriter (const FILE *file) {
                this->m_file = file;
            }
    
            void put_char (const char c) const {
                fwrite(&c, 1, 1, this->m_file);
            }
    
            void puts (const char string[]) const {
                const size_t length = strlen(string);
                fwrite(string, 1, length, this->m_file);
            }
    
        private:
            const FILE *m_file;
    };
    

    To use it, you'll also need to copy the file "printer.h" from PropWare into your project (assuming you're building using SimpleIDE)
    You'll need to rename your main class from *.c to *.cpp, since it now uses C++ classes. And here's the Printer class in action.
    #include "simpletools.h"                      // Include simpletools header
    #include "sdprinter.h"
    #include "printer.h"
    
    int MISO = 12;
    int SCLK = 13;
    int MOSI = 14;
    int SS   = 15;
    
    int main(void)                                // main function
    {
        int mout = sd_mount (MISO, SCLK, MOSI, SS);
    
        print("%d \n", mout);
        FILE* fp = fopen("test.txt", "w");          // Open a file for writing
    
        // Create our writer...
        SDWriter sdWriter(fp);
        // And wrap it in the common printer class
        PropWare::Printer sdPrinter(&sdWriter);
    
        // Pick _one_ of the following two lines
        sdPrinter.printf("Hello World %u,%u,%u", 2, 3, 11); // This one uses syntax you are already familiar with
        sdPrinter << "Hello World " << 2 << "," << 3 << "," << 11; // This one uses less code space
        
        fclose(fp);                                 // Close the file
        return 0;
    }
    

    You can save more space by eliminating the use of Parallax's print and switching it out for another Printer/PrintCapable object like so:
    #include "simpletools.h"                      // Include simpletools header
    #include <PropWare/printer/printer.h>
    
    class SimpleWriter : PropWare::PrintCapable {
        void put_char (const char c) const {
            putChar(c);
        }
    
        void puts (const char string[]) const {
            putStr(string);
        }
    };
    
    int main(void)                                // main function
    {
        const SimpleWriter serialWriter();
        PropWare::Printer serial(&serialWriter);
    
        // Highly efficient
        serial.println("Hello world!");
    
        // Equally efficient
        serial.printf("Hello world!" CRLF); // Note the explicit use of "CRLF" to add a newline
    
        // This pulls in a large chunk of code because it's the first time a parameter is used
        serial.printf("Hello, %s!" CRLF, "David");
    
        // This is your best bet - it pulls in *exactly* the amount of code you need and *none* of the code that you don't
        serial << "Hello, " << "David" << "!" CRLF;
    }
    

    Notice how writing to the SD card and writing to the serial terminal use the same PropWare class: the PropWare:: Printer. This means the formatting functions (converting ints to strings, converting floats to strings, etc) are shared. This saves a lot of code space.

    You could bring it all together with a main file like so:
    #include "simpletools.h"                      // Include simpletools header
    #include <PropWare/printer/printer.h>
    
    // Serial console
    class SimpleWriter : public PropWare::PrintCapable {
    public:
        SimpleWriter () {}
    
        void put_char (const char c) const {
            putChar(c);
        }
    
        void puts (const char string[]) const {
            putStr(string);
        }
    };
    
    // SD card
    class SDWriter : public PropWare::PrintCapable {
    public:
        SDWriter (const FILE *file) {
            this->m_file = file;
        }
    
        void put_char (const char c) const {
            fwrite(&c, 1, 1, this->m_file);
        }
    
        void puts (const char string[]) const {
            const size_t length = strlen(string);
            fwrite(string, 1, length, this->m_file);
        }
    
    private:
        const FILE *m_file;
    };
    
    int MISO = 12;
    int SCLK = 13;
    int MOSI = 14;
    int SS   = 15;
    
    int main(void)                                // main function
    {
        // Serial console
        const SimpleWriter serialWriter;
        const PropWare::Printer serial(&serialWriter);
    
        serial << "Hello, world!" CRLF;
    
        serial << "Mounting SD card... " CRLF;
        int mout = sd_mount (MISO, SCLK, MOSI, SS);
        serial << "Mount status (0 == success): " << mout << CRLF;
    
        serial << "Opening file" CRLF;
        FILE* fp = fopen("test.txt", "w");          // Open a file for writing
        // SD Card
        const SDWriter sdWriter(fp);
        const PropWare::Printer filePrinter(&sdWriter);
    
        serial << "File opened (stored in address " << (unsigned int) fp << ") " CRLF;
    
        filePrinter << "Hello " << 2 << ',' << 3 << ',' << 11 << '\n';
    
        serial << "File modified" CRLF;
    
        fclose(fp);
        serial << "File closed" CRLF;
        return 0;
    }
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-02 09:42
    Boblow45, if you are compiling in LMM mode try using CMM. The code size will be smaller, but it will run slower. If that doesn't work you could try including the attached file in your project. This file contains smaller versions of printf and fprintf. It saves 7K in LMM and 3.5K in CMM.
    c
    c
Sign In or Register to comment.