Shop OBEX P1 Docs P2 Docs Learn Events
fwrite() values to uSD - Page 2 — Parallax Forums

fwrite() values to uSD

2»

Comments

  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-12 10:35
    Thank You Dave, that worked perfectly, did not have to change a thing. Now that I can create a data file, write data to it, and then view it, the next thing I guess would be is deleting the file. Are there some built in functions in the SD program itself, for doing this?

    If I remember correctly the Spin SD program had some commands for doing this. Is the C version of the SD program the Spin version, or is it completely different code? Does the SD stuff reside somewhere within the simpletools lib or is there another lib that I should look at? If there is some existing SIDE SD code for deleting files already available, does anybody know where it is?

    Ray
  • edited 2015-01-12 10:49
    Hi Ray,

    If you want to write floating point to an SD card in a way that is text-editor friendly, here is an example. It could use some refinements, but it gets the job done for now. I also added code that the Propeller reads back into variables so that it can use the data for calculations if needed.

    Hi Dave Hein,

    Using stdio functions with floating point made programs too large, even in cmm mode. Since that's what the Learn libraries started supporting, simpletools versions of the functions without f at the ends of their names were created. For example, print does most of what printf does, but it does not take any more memory when a floating point variable is used. Since it does not do 'all' of what printf can do, we didn't want to call it printf. In the interest of making the transition easy, we called it print so that students who need to make the transition to stdio functions will just have to start adding an f after code they have been writing to get it to work on a computer. The pattern is the same with scan - scanf, sprint - sprintf, etc. ...and of course, we explain to the reader the that they are working with simpletools library variations of stdio functions early in the tutorials.
    /* 
      Store Float Vals to SD for Text Editor.c
    
      This example writes a list of floating point values to an SD card in 
      a format that will be readable when the SD is read by a computer and the
      file is viewed with a text editor.  This is especially useful for importing
      logged data into a spreadsheet.   
      
      Values that do not need to be viewed by a text editor do not need this
      program.  For example, the Propeller might be the only processor concerned
      with the values.  When that's the case, the application can simply write to
      and read from SD in binary format.  An example of that is here in the Try This
      section of:
      
      http://learn.parallax.com/propeller-c-simple-devices/sd-card-data
    
    */  
    
    
    #include "simpletools.h"                      // Include simpletools header    
    
    int DO = 22, CLK = 23, DI = 24, CS = 25;      // SD card pins on Propeller BOE
    
    float val;                                    // Declare value variable
    char s[32];                                   // 32 byte array
    
    int main(void)                                // main function
    {
      sd_mount(DO, CLK, DI, CS);                  // Mount SD card
    
      FILE* fp = fopen("test.txt", "w");          // Open a file for writing
      
      for(int i = -5; i < 15; i++)                // Repeat 20x (-5...14)
      {
        memset(s, ' ', 30);                       // 30 spaces into string
        s[30] = '\r';                             // Newline for Windows notepad
        s[31] = '\n';                             // String terminator
        val = ((float) i) * 10.0;                 // Emulate sensor reading
        sprint(s, "i = %d , val = %3.2f ",        // Data to s array as characters
                   i,       val);                 
        fwrite(s, 1, 32, fp);                     // Write line to file
      }  
      
      fclose(fp);                                 // Close file
      
      fp = fopen("test.txt", "r");                // Reopen file for reading
    
      int idx;
      for(int i = -5; i < 15; i++)                // go back through
      {
        memset(s, '\0', 32);                      // All characters to zero
        fread(s, 1, 32, fp);                      // Read the string
        
        print("As text for editor: \n");
        print("%s\n", s);
        
        print("As variables for Propeller:\n");
        sscan(s, "i = %d , val = %f",             // String values -> variables 
                  &idx,     &val);        
        print("idx = %d, val = %3.2f \n\n",       // Print variables
               idx,      val);
      }  
    
      fclose(fp);                                 // Close the file
    }
    
  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-12 11:35
    Thanks Andy, now do you have any functions handy for del, dir, format, ..., etc?


    Ray
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-01-12 11:39
    @Ray, the C function for deleting a file is remove(). As an example, to delete testfile.txt you would call remove("testfile.txt"). The functions for dir are opendir(), readdir() and closedir(). If you still have the source for filetest you can see examples of them being used.

    @Andy, I understand the need for smaller versions of the standard library, which is what I thought tinylib was. Maybe tinylib is too large, and there was a need for an even more compact library, but I would have still stayed with the standard C function names.
  • David BetzDavid Betz Posts: 14,511
    edited 2015-01-12 11:49
    Dave Hein wrote: »
    @Ray, the C function for deleting a file is remove(). As an example, to delete testfile.txt you would call remove("testfile.txt"). The functions for dir are opendir(), readdir() and closedir(). If you still have the source for filetest you can see examples of them being used.

    @Andy, I understand the need for smaller versions of the standard library, which is what I thought tinylib was. Maybe tinylib is too large, and there was a need for an even more compact library, but I would have still stayed with the standard C function names.
    Yes, stay with the standard names and just document the subset that you implement. Was any attempt made to shrink libtiny down to a size that was acceptable before creating a new library?
  • edited 2015-01-12 13:20
    Thanks guys. I'll save these along with other comments for the next time we revisit print vs. printf.
  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-12 14:08
    The program below now has a file and del command. I modified the code a bit, so as to work for this application. I will to spend some time figuring out the best code implementation for listing the dir of an SD card. I looked a filetest.c program that was written by Dave Hein, and it is somewhat complex to implement for this program, so I have to figure out the best way to re-write the code.

    So far the code below is a very specific application, and so much generic. I am looking at and butchering other code examples to make it work for this program. Not sure, but there might be some useful code examples in here that somebody could use, again not sure about that.

    Ray

    /*
      SAabsun.c
      Solar power unit monitor program.
      Jan 9, 2015
      Version 0.0.1
      Using ACTIVITYBOARD-SDMMC/XMMC External..., settings
      Version 0.0.2
      Added SD card access. Functionality to come in stages.
      Version 0.0.3
      Added a running clock.
      Version 0.0.4
      Added file and del commands.
    */
    #include "simpletools.h"
    #include "simpletext.h"
    #include "fdserial.h"
    #include "adcDCpropab.h"
    #include <sys/rtc.h>
    
    #define BUFFERLEN 10
    
    FILE *fp;
    serial *xbee;
    
    float v3,v2,v1,v0,y3,y1,y4;
    /* SD card */
    int DO = 22, CLK = 23, DI = 24, CS = 25;
    
    void menu();
    void mvolts();
    void avolts();
    void bvolts();
    void solpan();
    
    /* Time keeping */
    char timebuff[16];
    char datebuff[16];
    void Set_Clock();
    int getdst();
    int prompttime(char *prompt);
    void Get_Time();
    void Get_Date();
    
    /* SD card */
    void sd_File();
    void sd_Del();
    
    int main()
    {
      // Add startup code here.
    /* Start time keeping COG. */
    _rtc_start_timekeeping_cog();
    pause(100);
    /* Mount the SD file system. */
    sd_mount(DO, CLK, DI, CS);
    pause(100);
    
    
      char inBuff[40];
    /* Initialise the ADC. */
      adc_init(21, 20, 19, 18);
    
    /*                     Rx  Tx  mode  BAUD   */  
      xbee = fdserial_open(11, 10,  0,   9600);
      pause(50);
     
      while(1)
      {
        // Add main loop code here.
        if(fdserial_rxReady(xbee))
        {
          readStr(xbee, inBuff, 40);
          if(!strcmp(inBuff, "help")) menu();
          else if(!strcmp(inBuff, "mbat")) mvolts();
          else if(!strcmp(inBuff, "abat")) avolts();
          else if(!strcmp(inBuff, "bbat")) bvolts();
          else if(!strcmp(inBuff, "solpan")) solpan();
          else if(!strcmp(inBuff, "setclock")) Set_Clock();
          else if(!strcmp(inBuff, "time")) Get_Time();
          else if(!strcmp(inBuff, "date")) Get_Date();
          else if(!strcmp(inBuff, "file")) sd_File();
          else if(!strcmp(inBuff, "del")) sd_Del();
          else
          {
            writeLine(xbee,"Unknown Command.");    
          }      
        }    
      }
      return 0;  
    }
    
    void menu()
    {
      writeStr(xbee,"Menu -  help, mbat, abat, bbat, solpan \n");
      writeStr(xbee,"        setclock, time, date, date, file \n");
      writeStr(xbee,"        del, \n");
    }
    
    /*
    Check the voltage of the Parallax Power Pack that is 
    powering the Activity Board.
    */
    void mvolts()
    {
      char inBuff[2];
      char outBuff[10];
    /*              ADC port 3  load.          */
    /* This now uses [V+ 10K_|_10K V-] resistor setup.   */
      v3 = adc_volts(3);
      v3 = (v3*2.00);
      
      writeStr(xbee,"mBattery ");
      writeFloat(xbee,v3);   // This now showing the correct voltage.
      writeStr(xbee," Volts\n");
      writeStr(xbee,"Log this?(y/n) \n");
      writeStr(xbee,"? ");
      readStr(xbee, inBuff, 2);
      if(!strcmp(inBuff, "y"))
      {
        Get_Time();
        Get_Date();
        fp = fopen("Sol_dat.txt", "a+");
        fprintf(fp,"mbat %s %s %f V;\r\n",datebuff,timebuff,v3);
        fclose(fp);
      }
      else
      {
        writeStr(xbee,"Done\n");
      }  
    }
    
    /*
    Check the voltage of the primary battery for the solar system.
    */
    void avolts()
    {
    /*                   ADC port 2 load.           */
    /* This now uses [V+ 1K_1K_1K_|_1K V-] resistor setup.   */
    /* This will be worked in after the battery gets
       put on line with the PWM solar controller. */
    //  float y3,y1;
      int x;
      for(x=0;x<1000;x++)
      {
        y1 = adc_volts(2);
        y3 = y3 + y1;
      }
      y3 = (y3/1000);
      y3 = (y3*4.00);
      v2 = y3;
    
      writeStr(xbee,"aBattery ");
      writeFloat(xbee,v2);  // After manipulation, reads correct voltage.
      writeStr(xbee," Volts\n");  
    }
    
    /*
    Check the voltage of the secondary battery for the solar system.
    */
    void bvolts()
    {
    /*                   ADC port 1 load.            */
    /* This now uses [V+ 1K_1K_1K_|_1K V-] resistor setup.   */
    /* This will be worked in after the battery gets
       put on line with the PWM solar controller. */
    //  float y3,y1;
      int x;
      for(x=0;x<1000;x++)
      {
        y1 = adc_volts(1);
        y4 = y4 + y1;
      }
      y4 = (y4/1000);
      y4 = (y4*4.00);
      v1 = y4;
    
      writeStr(xbee,"bBattery ");
      writeFloat(xbee,v1);  // After manipulation, reads correct voltage.
      writeStr(xbee," Volts\n");
    }
    
    /*
    Check voltage levels of the solar panel.
    */
    void solpan()
    {
    /*                   ADC port 1 load.            */
    /* This now uses [V+ 1K_1K_1K_|_1K V-] resistor setup.   */
      v0 = adc_volts(1);
      v0 =(v0*4.00);   // Calculation based on manipulation
                       // to actual battery voltage reading.
      
      writeStr(xbee,"Solar Panel ");
      writeFloat(xbee,v0);  // After manipulation, reads correct voltage.
      writeStr(xbee," Volts\n");
    }
    
    
    
    /* Time keeping functions. */
    void Set_Clock()
    {
      struct timeval tv;
      struct tm t;
    
      t.tm_isdst = getdst();
      t.tm_year = prompttime("Year(xxxx) ")-1900;
      t.tm_mon = prompttime("Month(xx) ")-1;
      t.tm_mday = prompttime("Day of the month ");
      t.tm_hour = prompttime("Hour ");
      t.tm_min = prompttime("Minute ");
      t.tm_sec = prompttime("Second ");
    
      tv.tv_sec = mktime(&t);
      settimeofday(&tv, 0);
    }
    
    int getdst()
    {
      int rc = 0;
      char inBuff[2];
    
      writeStr(xbee,"Use daylight savings time (y/n)");
      readStr(xbee, inBuff, 2);
      if(!strcmp(inBuff, "y"))
      {
        rc = 1;
      }
      else
      {
        rc = 0;
      }  
      return rc;
    }
    
    int prompttime(char *prompt)
    {
      int rc = 0;
      char *endp;
      char buffer[BUFFERLEN];
    
      do
      {
        writeStr(xbee,"Enter: ");
        writeStr(xbee,prompt);
        readStr(xbee,buffer,10);
    
        rc = strtol(buffer, &endp, 10);
    
        if(endp == buffer)
        {
          if('\n' == *endp)
          {
            rc = 0;
            break;
          }
            writeStr(xbee,"Invalid entry ... Please enter a number,\n");
        }
      } while(endp == buffer);
      return rc;
    }
    
    void Get_Time()
    {
    //  char timebuff[16];
      time_t now = 0;
    
      now = time(&now);
      strftime(timebuff,16,"%T",localtime(&now));
      //print("%s\n",timebuff);
      writeStr(xbee,timebuff);
      writeStr(xbee,"\n");
    }
    
    void Get_Date()
    {
    //  char timebuff[16];
      time_t now = 0;
    
      now = time(&now);
      strftime(datebuff,16,"%b %d, %Y",localtime(&now));
      writeStr(xbee,datebuff);
      writeStr(xbee,"\n");
    }
    
    /* SD card */
    /* Display the contents of the data file. */
    void sd_File()
    {
      char buffer[80];
      
      fp = fopen("Sol_dat.txt","r");
      if(fp == 0)
      {
        writeStr(xbee,"No file to open!\n");
      }
      else
      {  
        while(fgets(buffer, 80, fp))
        {
          writeStr(xbee, buffer);
        }
        fclose(fp);
      }  
    }
    
    /* Delete the file */
    void sd_Del()
    {
      fp = fopen("Sol_dat.txt","r");
      if(fp == 0)
      {
        writeStr(xbee,"No file to delete!\n");
      }
      else
      {  
        remove("Sol_dat.txt");
      }  
    }
    
    
  • zappmanzappman Posts: 418
    edited 2015-01-12 15:52
    Rsadeika wrote: »
    ... Not sure, but there might be some useful code examples in here that somebody could use, again not sure about that.

    Ray

    Hi Ray,

    Yes, there are some useful code examples.

    1) Using the A/D section of the Activity Board
    2) Using the microSD card section of the Activity Board to save data
    3) Learning what include <sys/rtc.h> is, a Soft RTC at http://propgcc.googlecode.com/hg/doc/Library.html#RTC
    David Betz wrote:

    Re: fwrite() values to uSD
    Ray, there are two buttons on the bottom tool bar that make the project view and build status visible. Unfortunately, these settings don't persist after you exit, and you need to click on them again to show the windows after startup. I think Parallax should document this better, and make the settings persist after exiting.
    It probably wouldn't be too hard to add a check box to the options dialog (or whatever it is called) to cause those settings to persist. I'll have to check with Parallax to see if they would be okay with that.
    +1 on make the settings persist after exiting
    Dave Hein wrote:

    Re: fwrite() values to uSD

    @Andy, I understand the need for smaller versions of the standard library, which is what I thought tinylib was. Maybe tinylib is too large, and there was a need for an even more compact library, but I would have still stayed with the standard C function names.

    +1 I would have still stayed with the standard C function names. If you are a beginner, like me, trying to learn C using SimpleIDE and an Activity Board; the changed function names make it harder. I can't easily follow use examples in books that teach ANSI C. I would think most people would prefer to learn and use ANSI C function names verses the bastardized Propeller C function names.
    bas·tard·ize
    ˈbastərˌdīz/
    verb
    past tense: bastardized; past participle: bastardized

    1.
    corrupt or debase (something such as a language or art form), typically by adding new elements.
    "a strange, bastardized form of French"

    synonyms: adulterate, corrupt, contaminate, weaken, dilute, taint, pollute, debase, distort
    "it is unthinkable that I would bastardize my values"
  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-13 04:24
    Below is a butchered version of the List command as presented by Dave Hein. In this form, it is now the dir command, which runs as expected, and it does not freeze up the program. The harder part is how to implement the file attributes in my version, and how much should be shown. I will present the whole program after the List function gets looked at carefully, and any other suggestions are added.

    Ray

    void sd_List()
    {
      int i, j;
      int argc = 0;
      char **argv;
      int32_t count = 0;
      char *path;
      uint32_t filesize;
      char fname[13];
      char *ptr;
      DIR *dirp;
      int column;
      int prevlen;
      struct dirent *entry;
      char drwx[5];
      uint32_t longflag = 0;
      
    // List directories
        for (j = 1; j < argc || count == 0; j++)
        {
            if (count == 0)
            {
                count--;
                path = "./";
            }
            //else if (argv[j][0] == '-')
            //    continue;
            else
                path = argv[j];
    
            if (count >= 2)
                //fprintf(stdoutfile, "\n%s:\n", path);
                writeStr(xbee,"\n");
                writeStr(xbee,path);
    
            dirp = opendir(path);
    
            if (!dirp)
            {
                perror(path);
                continue;
            }
    
            column = 0;
            prevlen = 14;
            while (entry = readdir(dirp))
            {
                if (entry->name[0] == '.') continue;
                ptr = fname;
                for (i = 0; i < 8; i++)
                {
                    if (entry->name[i] == ' ') break;
                    *ptr++ = tolower(entry->name[i]);
                }
                if (entry->name[8] != ' ')
                {
                    *ptr++ = '.';
                    for (i = 8; i < 11; i++)
                    {
                        if (entry->name[i] == ' ') break;
                        *ptr++ = tolower(entry->name[i]);
                    }
                }
                *ptr = 0;
                filesize = entry->filesize_3;
                filesize = (filesize << 8) | entry->filesize_2;
                filesize = (filesize << 8) | entry->filesize_1;
                filesize = (filesize << 8) | entry->filesize_0;
                strcpy(drwx, "-rw-");
                if (entry->attr & ATTR_READ_ONLY)
                    drwx[2] = '-';
                if (entry->attr & ATTR_ARCHIVE)
                    drwx[3] = 'x';
                if (entry->attr & ATTR_DIRECTORY)
                {
                    drwx[0] = 'd';
                    drwx[3] = 'x';
                }
                if (longflag)
                {
                    //fprintf(stdoutfile, "%s %8d %s\n", drwx, filesize, fname);
                    writeStr(xbee,drwx);
                    writeStr(xbee,filesize);
                    writeStr(xbee,fname);
                    writeStr(xbee,"\n");
                }
                else if (++column == 5)
                {
                    for (i = prevlen; i < 14; i++) writeStr(xbee," ");
                     //fprintf(stdoutfile, " ");
                    //fprintf(stdoutfile, "%s\n", fname);
                    writeStr(xbee,fname);
                    writeStr(xbee,"\n");
                    column = 0;
                    prevlen = 14;
                }
                else
                {
                    for (i = prevlen; i < 14; i++) writeStr(xbee," ");
                    //fprintf(stdoutfile, " ");
                    prevlen = strlen(fname);
                    //fprintf(stdoutfile, "%s", fname);
                    writeStr(xbee,fname);
                }
            }
            closedir(dirp);
            if (!longflag && column)
                //fprintf(stdoutfile, "\n");
                writeStr(xbee,"\n");
        }
    }
    
  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-13 10:41
    The program below now has a functional 'dir' command with limited attributes. Code Size 106,084 bytes (107,108 total). Not sure what comes next.

    Ray

    /*
      SAabsun.c
      Solar power unit monitor program.
      You need to do setclock, to get the correct time and date;
      
      Jan 9, 2015
      Version 0.0.1
      Using ACTIVITYBOARD-SDMMC/XMMC External..., settings
      Jan 10, 2015
      Version 0.0.2
      Added SD card access. Functionality to come in stages.
      Jan 11, 2015
      Version 0.0.3
      Added a running clock.
      Jan 13, 2015
      Version 0.0.4
      Added file, del, dir commands.
    */
    #include "simpletools.h"
    #include "simpletext.h"
    #include "fdserial.h"
    #include "adcDCpropab.h"
    #include <sys/rtc.h>
    
    #define BUFFERLEN 10
    
    FILE *fp;
    serial *xbee;
    
    float v3,v2,v1,v0,y3,y1,y4;
    /* SD card */
    int DO = 22, CLK = 23, DI = 24, CS = 25;
    
    void menu();
    void mvolts();
    void avolts();
    void bvolts();
    void solpan();
    
    /* Time keeping */
    char timebuff[16];
    char datebuff[16];
    void Set_Clock();
    int getdst();
    int prompttime(char *prompt);
    void Get_Time();
    void Get_Date();
    
    /* SD card */
    void sd_File();
    void sd_Del();
    void sd_List();
    
    int main()
    {
      // Add startup code here.
    /* Start time keeping COG. */
    _rtc_start_timekeeping_cog();
    pause(100);
    /* Mount the SD file system. */
    sd_mount(DO, CLK, DI, CS);
    pause(100);
    
    
      char inBuff[40];
    /* Initialise the ADC. */
      adc_init(21, 20, 19, 18);
    
    /*                     Rx  Tx  mode  BAUD   */  
      xbee = fdserial_open(11, 10,  0,   9600);
      pause(50);
     
      while(1)
      {
        // Add main loop code here.
        if(fdserial_rxReady(xbee))
        {
          readStr(xbee, inBuff, 40);
          if(!strcmp(inBuff, "help")) menu();
          else if(!strcmp(inBuff, "mbat")) mvolts();
          else if(!strcmp(inBuff, "abat")) avolts();
          else if(!strcmp(inBuff, "bbat")) bvolts();
          else if(!strcmp(inBuff, "solpan")) solpan();
          else if(!strcmp(inBuff, "setclock")) Set_Clock();
          else if(!strcmp(inBuff, "time")) Get_Time();
          else if(!strcmp(inBuff, "date")) Get_Date();
          else if(!strcmp(inBuff, "file")) sd_File();
          else if(!strcmp(inBuff, "del")) sd_Del();
          else if(!strcmp(inBuff, "dir")) sd_List();
          else
          {
            writeLine(xbee,"Unknown Command.");    
          }      
        }    
      }
      return 0;  
    }
    
    void menu()
    {
      writeStr(xbee,"Menu -  help, mbat, abat, bbat, solpan \n");
      writeStr(xbee,"        setclock, time, date \n");
      writeStr(xbee,"        file, del, dir \n");
    }
    
    /*
    Check the voltage of the Parallax Power Pack that is 
    powering the Activity Board.
    */
    void mvolts()
    {
      char inBuff[2];
      char outBuff[10];
    /*              ADC port 3  load.          */
    /* This now uses [V+ 10K_|_10K V-] resistor setup.   */
      v3 = adc_volts(3);
      v3 = (v3*2.00);
      
      writeStr(xbee,"mBattery ");
      writeFloat(xbee,v3);   // This now showing the correct voltage.
      writeStr(xbee," Volts\n");
      writeStr(xbee,"Log this?(y/n) \n");
      writeStr(xbee,"? ");
      readStr(xbee, inBuff, 2);
      if(!strcmp(inBuff, "y"))
      {
        Get_Time();
        Get_Date();
        fp = fopen("Sol_dat.txt", "a+");
        fprintf(fp,"mbat %s %s %f V;\r\n",datebuff,timebuff,v3);
        fclose(fp);
      }
      else
      {
        writeStr(xbee,"Done\n");
      }  
    }
    
    /*
    Check the voltage of the primary battery for the solar system.
    */
    void avolts()
    {
    /*                   ADC port 2 load.           */
    /* This now uses [V+ 1K_1K_1K_|_1K V-] resistor setup.   */
    /* This will be worked in after the battery gets
       put on line with the PWM solar controller. */
    //  float y3,y1;
      int x;
      for(x=0;x<1000;x++)
      {
        y1 = adc_volts(2);
        y3 = y3 + y1;
      }
      y3 = (y3/1000);
      y3 = (y3*4.00);
      v2 = y3;
    
      writeStr(xbee,"aBattery ");
      writeFloat(xbee,v2);  // After manipulation, reads correct voltage.
      writeStr(xbee," Volts\n");  
    }
    
    /*
    Check the voltage of the secondary battery for the solar system.
    */
    void bvolts()
    {
    /*                   ADC port 1 load.            */
    /* This now uses [V+ 1K_1K_1K_|_1K V-] resistor setup.   */
    /* This will be worked in after the battery gets
       put on line with the PWM solar controller. */
    //  float y3,y1;
      int x;
      for(x=0;x<1000;x++)
      {
        y1 = adc_volts(1);
        y4 = y4 + y1;
      }
      y4 = (y4/1000);
      y4 = (y4*4.00);
      v1 = y4;
    
      writeStr(xbee,"bBattery ");
      writeFloat(xbee,v1);  // After manipulation, reads correct voltage.
      writeStr(xbee," Volts\n");
    }
    
    /*
    Check voltage levels of the solar panel.
    */
    void solpan()
    {
    /*                   ADC port 1 load.            */
    /* This now uses [V+ 1K_1K_1K_|_1K V-] resistor setup.   */
      v0 = adc_volts(1);
      v0 =(v0*4.00);   // Calculation based on manipulation
                       // to actual battery voltage reading.
      
      writeStr(xbee,"Solar Panel ");
      writeFloat(xbee,v0);  // After manipulation, reads correct voltage.
      writeStr(xbee," Volts\n");
    }
    
    
    
    /* Time keeping functions. */
    void Set_Clock()
    {
      struct timeval tv;
      struct tm t;
    
      t.tm_isdst = getdst();
      t.tm_year = prompttime("Year(xxxx) ")-1900;
      t.tm_mon = prompttime("Month(xx) ")-1;
      t.tm_mday = prompttime("Day of the month ");
      t.tm_hour = prompttime("Hour ");
      t.tm_min = prompttime("Minute ");
      t.tm_sec = prompttime("Second ");
    
      tv.tv_sec = mktime(&t);
      settimeofday(&tv, 0);
    }
    
    int getdst()
    {
      int rc = 0;
      char inBuff[2];
    
      writeStr(xbee,"Use daylight savings time (y/n)");
      readStr(xbee, inBuff, 2);
      if(!strcmp(inBuff, "y"))
      {
        rc = 1;
      }
      else
      {
        rc = 0;
      }  
      return rc;
    }
    
    int prompttime(char *prompt)
    {
      int rc = 0;
      char *endp;
      char buffer[BUFFERLEN];
    
      do
      {
        writeStr(xbee,"Enter: ");
        writeStr(xbee,prompt);
        readStr(xbee,buffer,10);
    
        rc = strtol(buffer, &endp, 10);
    
        if(endp == buffer)
        {
          if('\n' == *endp)
          {
            rc = 0;
            break;
          }
            writeStr(xbee,"Invalid entry ... Please enter a number,\n");
        }
      } while(endp == buffer);
      return rc;
    }
    
    void Get_Time()
    {
    //  char timebuff[16];
      time_t now = 0;
    
      now = time(&now);
      strftime(timebuff,16,"%T",localtime(&now));
      //print("%s\n",timebuff);
      writeStr(xbee,timebuff);
      writeStr(xbee,"\n");
    }
    
    void Get_Date()
    {
    //  char timebuff[16];
      time_t now = 0;
    
      now = time(&now);
      strftime(datebuff,16,"%b %d, %Y",localtime(&now));
      writeStr(xbee,datebuff);
      writeStr(xbee,"\n");
    }
    
    /* SD card */
    /* Display the contents of the data file. */
    void sd_File()
    {
      char buffer[80];
      
      fp = fopen("Sol_dat.txt","r");
      if(fp == 0)
      {
        writeStr(xbee,"No file to open!\n");
      }
      else
      {  
        while(fgets(buffer, 80, fp))
        {
          writeStr(xbee, buffer);
        }
        fclose(fp);
      }  
    }
    
    /* Delete the file */
    void sd_Del()
    {
      fp = fopen("Sol_dat.txt","r");
      if(fp == 0)
      {
        writeStr(xbee,"No file to delete!\n");
      }
      else
      {  
        remove("Sol_dat.txt");
      }  
    }
    
    
    void sd_List()
    {
      int i, j;
      int argc = 0; //0;
      char **argv;
      int32_t count = 0;
      char *path;
      uint32_t filesize;
      char fname[13];
      char *ptr;
      DIR *dirp;
      int column;
      int prevlen;
      struct dirent *entry;
      char drwx[5];
      uint32_t longflag = 1; // 0 = no attributes, 1 = attributes
      
    // List directories
        for (j = 1; j < argc || count == 0; j++)
        {
            if (count == 0)
            {
                count--;
                path = "./";
            }
            //else if (argv[j][0] == '-')
            //    continue;
            else
                path = argv[j];
    
            if (count >= 2)
                //fprintf(stdoutfile, "\n%s:\n", path);
                writeStr(xbee,"\n");
                writeStr(xbee,path);
    
            dirp = opendir(path);
    
            if (!dirp)
            {
                perror(path);
                continue;
            }
    
            column = 0;
            prevlen = 14;
            while (entry = readdir(dirp))
            {
                if (entry->name[0] == '.') continue;
                ptr = fname;
                for (i = 0; i < 8; i++)
                {
                    if (entry->name[i] == ' ') break;
                    *ptr++ = tolower(entry->name[i]);
                }
                if (entry->name[8] != ' ')
                {
                    *ptr++ = '.';
                    for (i = 8; i < 11; i++)
                    {
                        if (entry->name[i] == ' ') break;
                        *ptr++ = tolower(entry->name[i]);
                    }
                }
                *ptr = 0;
                filesize = entry->filesize_3;
                filesize = (filesize << 8) | entry->filesize_2;
                filesize = (filesize << 8) | entry->filesize_1;
                filesize = (filesize << 8) | entry->filesize_0;
                strcpy(drwx, "-rw-");
                if (entry->attr & ATTR_READ_ONLY)
                    drwx[2] = '-';
                if (entry->attr & ATTR_ARCHIVE)
                    drwx[3] = 'x';
                if (entry->attr & ATTR_DIRECTORY)
                {
                    drwx[0] = 'd';
                    drwx[3] = 'x';
                }
                if (longflag)
                {
                    //fprintf(stdoutfile, "%s %8d %s\n", drwx, filesize, fname);
                    //writeStr(xbee,drwx);
                    //writeDec(xbee,filesize);
                    //writeStr(xbee,fname);
                    /* Changed this to filname rw filesize. */
                    writeStr(xbee,fname);
                    writeStr(xbee," ");
                    writeStr(xbee,drwx);
                    writeStr(xbee," ");
                    writeDec(xbee,filesize);
                    writeStr(xbee,"\n");
                }
                else if (++column == 5)
                {
                    for (i = prevlen; i < 14; i++) writeStr(xbee," ");
                     //fprintf(stdoutfile, " ");
                    //fprintf(stdoutfile, "%s\n", fname);
                    writeStr(xbee,fname);
                    writeStr(xbee,"\n");
                    column = 0;
                    prevlen = 14;
                }
                else
                {
                    for (i = prevlen; i < 14; i++) writeStr(xbee," ");
                    //fprintf(stdoutfile, " ");
                    prevlen = strlen(fname);
                    //fprintf(stdoutfile, "%s", fname);
                    writeStr(xbee,fname);
                }
            }
            closedir(dirp);
            if (!longflag && column)
                //fprintf(stdoutfile, "\n");
                writeStr(xbee,"\n");
        }
    }
    
  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-14 08:53
    Today I put the program online to see how it is working, the area of concern is avolts() function. When I use the function it seems like it takes an awful long time to do the computation. Before, when I had the float v2 and y3 as local variables, the function ran much faster, but I was not getting the correct results. When I made float v2 and y3 as global, I get the correct results but the function takes a long time to work. Anybody have a remedy for this, or at least a guess as to what the problem might be?

    So far I am satisfied how the file, dir, and del commands are working. I am not sure if I want to implement mkdir, deldir, and cd just yet, but then I would have to include a format command, have not seen any examples for doing that.

    Ray
    /*
    Check the voltage of the primary battery for the solar system.
    */
    void avolts()
    {
      char inBuff[2];
    /*                   ADC port 2 load.           */
    /* This now uses [V+ 1K_1K_1K_|_1K V-] resistor setup.   */
    /* This will be worked in after the battery gets
       put on line with the PWM solar controller. */
    
      int x;
      for(x=0;x<1000;x++)
      {
        y1 = adc_volts(2);
        y3 = y3 + y1;
      }
      y3 = (y3/1000);
      y3 = (y3*4.00);
      v2 = y3;
    
      writeStr(xbee,"aBattery ");
      writeFloat(xbee,v2);  // After manipulation, reads correct voltage.
      writeStr(xbee," Volts\n");
      writeStr(xbee,"Log this?(y/n) \n");
      writeStr(xbee,"? ");
      readStr(xbee, inBuff, 2);
      if(!strcmp(inBuff, "y"))
      {
        Get_Time();
        Get_Date();
        fp = fopen("Sol_dat.txt", "a+");
        fprintf(fp,"abat %s %s %f V;\r\n",datebuff,timebuff,v2);
        fclose(fp);
      }
      else
      {
        writeStr(xbee,"Done\n");
      }    
    }
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-01-14 10:10
    You need to initialize y3 to zero before the "for(x=0;x<1000;x++)" loop. The reason it didn't work when you made y3 a local variable is that stack variables are uninitialized, and will have an unpredicatable initial value. So when you do "y3 = y3 + y1" you are adding the correct values to some unkown initial value. The reason is looks like its working when y3 is global is because y3 starts with a zero value. However, subsequent calls to avolt will use an initial value that is 4.00 times the previous average value. Since you are averaging over 1000 samples the error is only 4/1000 = 0.4%.

    I'm not sure why it runs slower when y3 is global. The generated code may be larger and causing a cache miss every loop. When you are using a local variable the loop might be able to run without a cache miss. Make y3 and v2 local, and initialize y3 to zero.
  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-14 11:35
    Thanks Dave. Making the changes improved the compute time, and I am getting the expected values. The surprising thing about removing the yx values from global and making them local, Code Size 63,540 bytes (64,556 total). What the heck is going on?? I still think there is something weird going on with either PropGCC , SimpleIDE, or both concerning this local verses global declarations, but that just might be me.

    Ray
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-01-14 11:48
    Can you post your code using local values? I get 105,620 bytes independent of whether they are local or global. If you are only getting 63,540 byte I suspect something has gotten optimized out. Also post your .side file.
  • RsadeikaRsadeika Posts: 3,822
    edited 2015-01-14 12:01
    OK, I just zipped the project, you will get what I got.

    Ray
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-01-14 13:00
    The problem is the variable y1. There is a library function called y1, which is the "Bessel function of the second kind of order 1". I had forgotten about this, but it catches people every so often. You should avoid making y1 a global variable. Also avoid global variables named y0, yn, j0, j1 and jn. You can get around this by adding the keyword "static" to the declaration. Or you can make it a local variable. By making it an external global variable the linker pulls in the library that contains the y1 function even though you declared y1 as a variable.

    In general, it's best to avoid global variables with short names. One restriction with C is that all global variables must have unique names or they will be treated as the same variable/function.
  • msrobotsmsrobots Posts: 3,701
    edited 2015-01-14 15:11
    Seems to me that one also should avoid library functions with short names. y0,y1 and yn are not really hinting one to a Bessel function...

    Enjoy!

    Mike
Sign In or Register to comment.