fwrite() values to uSD
Below is my test function for writing values to the uSD card. I finally got something to write to the file, but it is gibberish, I am not seeing my float number. The variable v3 has been declared as global float v3, but it seems like &v3 is not doing the deed. Anybody have a remedy for this?
Thanks
Ray
Thanks
Ray
void mvolts()
{
char inBuff[2];
/* 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");
readStr(xbee, inBuff, 2);
if(!strcmp(inBuff, "y"))
{
fp = fopen("Sol_dat.txt", "a+");
fwrite(&v3,sizeof(float),1,fp);
fclose(fp);
}
else
{
writeStr(xbee,"Done");
}
}

Comments
How large is your executable. With both floating point and file I/O it might be close to 32K, and you might be running out of memory. What memory model are you using? Can you reduce your code down to a small program that shows the problem, and post the code?
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. */ #include "simpletools.h" #include "simpletext.h" #include "fdserial.h" #include "adcDCpropab.h" 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(); /* void led26(); */ int main() { // Add startup code here. /* Start the new COGs. */ //int *cog1 = cog_run(&led26, 10); //pause(100); /* Mount the SD file system. */ sd_mount(DO, CLK, DI, CS); pause(100); fp = fopen("Sol_dat.txt", "a+"); 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 { writeLine(xbee,"Unknown Command."); } } } return 0; } void menu() { writeStr(xbee,"Menu - help, mbat, abat, bbat, solpan \n"); } /* Check the voltage of the Parallax Power Pack that is powering the Activity Board. */ void mvolts() { char inBuff[2]; /* 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"); readStr(xbee, inBuff, 2); if(!strcmp(inBuff, "y")) { fp = fopen("Sol_dat.txt", "a+"); fwrite(&v3,sizeof(float),1,fp); fclose(fp); } else { writeStr(xbee,"Done"); } } /* 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"); } /* Future COG functions when they are able to run in XMMC space. */ /* void led26() { while(1) { high(26); pause(500); low(26); pause(500); } } */Also, try commenting out the call to sd_mount. I don't think it's needed in XMMC mode when using the SD as external memory. The call to sd_mount may be conflicting with the SD cache driver.
The size of float variables is 4 bytes, so sizeof(float) should have a value of 4.
I don't see where you read the file Sol_dat.txt, so how do you know that the file is not being written correctly? You might try writing a program using fopen("Sol_dat.txt", "r"), and using fread(&x, 1, 4, fp) to read back a value.
Thanks Dave I will try the other recommendations also.
Ray
Ray
Can you try running the attached test program. You will need to change the board type to ACTIVITYBOARD-SDXMM before you build it. It should print out the following lines when you run it: Every time you run it the same four lines will be repeated an additional time.
BTW, fwrite will write the binary values of the floating point numbers, and not the ASCII values. So if you are seeing gibberish it may be because you are trying to interpret it as ASCII instead of binary.
Dave
Edit: Oops, I just noticed that Dave Hein already mentioned this possibility.
I jokingly mentioned SimpleIDE RC5, well it looks like probably RC2 will be the last one before it goes to SimpleIDE 1.0. And I doubt that it will contain any of the features that I have been squawking about; I guess I could go the command line route with PropGCC. Make files, I get a headache just saying those two words, but what other choice is there?
This latest program that I am developing will probably have to get makeover, meaning remove SimpleIDE and features, and start from the ground level of PropGCC. Hopefully some of the original developers, of PropGCC, will stick around to answer some queries as they arise, if not then there is always...
Ray
As a second thought, you might consider trying PropWare:
http://forums.parallax.com/showthread.php/157005-FYI-PropWare-Complete-build-system-and-library-for-PropGCC?highlight=propware
This was written by SwimDude0614 and uses cmake which is supposed to be easier to use than make. I'm sure he'd be happy to help you get started. I haven't had time to try it myself but he's put a lot of work into it and the library has many drivers for common Propeller peripherals.
Has anybody created a short tutorial for this? I went to the PropGCC site, and found a lot of fragmented information about usage. About PropWare, I am well aware of its existence, but it looks like there is a trend that is starting to develop here, people start developing a program for use, and then it goes dormant, and then the developer disappears.
I know this is just a hobby, for me at least, but how many times can I start from scratch?
Ray
Edit: Also, make is not a Parallax tool and neither is gcc. There is lots of information on the web about how to use both. I know that's not a real substitute for good Propeller-based documentation but it is a start.
As to the little program that Dave provided, I tried it out and it worked as described. So I know that from a base start, at least that works. Now I will have to figure how to use the correct sequence of commands to compile and load a program to the Propeller, from the command line.
Ray
Now back to resolving the problem with writing float values to the SD card. My full intent with the function will be to datalog the specific data, meaning the line of data in the xxx.txt file would look something like this: 'mbat 01102015 7.9567 V'. If I ever figure out a way of manipulating the values on the file, I have to make sure that I am doing something cogent up front.
The code below is my recent attempt to put ascii string in the xxx.txt file. I am using sprint(), but it seems to only convert the right side of the decimal part of the float number. If I have something like v3 = 7.99675, after the use of sprint(), I only see .99675, no legible left side of decimal. I think I am getting close but not yet there.
Ray
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"); readStr(xbee, inBuff, 2); if(!strcmp(inBuff, "y")) { fp = fopen("Sol_dat.txt", "a+"); sprintf(outBuff,"%f",v3); fwrite(outBuff,sizeof(float),1,fp); fread(outBuff,1,1,fp); fclose(fp); writeStr(xbee,outBuff); } else { writeStr(xbee,"Done"); } }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"); readStr(xbee, inBuff, 2); if(!strcmp(inBuff, "y")) { fp = fopen("Sol_dat.txt", "a+"); sprintf(outBuff,"%f",v3); fwrite(outBuff,strlen(outBuff),1,fp); // why do you need to read the file? You already have the string in outBuff. // if you do want to re-read it from the file, you'll have to fseek to the start of the file and then use fscanf to read the floa // fread(outBuff,1,1,fp); fclose(fp); writeStr(xbee,outBuff); } else { writeStr(xbee,"Done"); } }I have the code example that jazzed provided, last century I think :-), for a softRTC, so I will try to work that into the program for date and time stuff, but, how will the program deal with the COG that the softRTC program uses, in XMMC mode? I am assume that the COG that gets started is to have a running clock going? If this does not work, then I would need some other way of having a running clock.
Then the next step will be for function that allows for opening the xxx.txt file and be able to see the contents of the file on the terminal screen. Not sure how that would work in the context of SimpleIDE simpletools structure.
Ray
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"); readStr(xbee, inBuff, 2); if(!strcmp(inBuff, "y")) { fp = fopen("Sol_dat.txt", "a+"); fwrite("mbat ",1,5,fp); sprintf(outBuff,"%f",v3); fwrite(outBuff,strlen(outBuff),1,fp); fwrite(";/n",1,3,fp); //fread(outBuff,1,1,fp); fclose(fp); //writeStr(xbee,outBuff); } else { writeStr(xbee,"Done"); } }The program so far: Code Size 93,180 bytes (94,100 total). How large can I make the program before I start to see it run at snails pace?
Ray
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")) { fp = fopen("Sol_dat.txt", "a+"); fprintf(fp,"mbat %f V;\r\n",v3); fclose(fp); } else { writeStr(xbee,"Done"); } }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. */ #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(); /* void led26(); */ int main() { // Add startup code here. /* Start the new COGs. */ //int *cog1 = cog_run(&led26, 10); //pause(100); /* Mount the SD file system. */ /* Start time keeping COG. */ _rtc_start_timekeeping_cog(); pause(100); 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 { writeLine(xbee,"Unknown Command."); } } } return 0; } void menu() { writeStr(xbee,"Menu - help, mbat, abat, bbat, solpan \n"); writeStr(xbee," setclock, time, date, date, \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"); } } /* 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"); } /* Future COG functions when they are able to run in XMMC space. */ /* void led26() { while(1) { high(26); pause(500); low(26); pause(500); } } */ /* 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]; //print("Use daylight savings time [y/n] ? "); writeStr(xbee,"Use daylight savings time (y/n)"); //fflush(stdout); readStr(xbee, inBuff, 2); if(!strcmp(inBuff, "y")) { rc = 1; } else { rc = 0; } //rc = (getchar() == 'y') ? 1 : 0; //getchar(); return rc; } int prompttime(char *prompt) { int rc = 0; char *endp; char buffer[BUFFERLEN]; do { writeStr(xbee,"Enter: "); writeStr(xbee,prompt); //fflush(stdout); //fgets(buffer, BUFFERLEN,stdin); readStr(xbee,buffer,10); //fflush(stdin); rc = strtol(buffer, &endp, 10); if(endp == buffer) { if('\n' == *endp) { rc = 0; break; } //print("Invalid entry \"%c....\" Please enter a number.\n", *endp); 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)); //print("%s\n",timebuff); writeStr(xbee,datebuff); writeStr(xbee,"\n"); }Ray
/* SD card */ void sd_File() { int val = 500; fp = fopen("Sol_dat.txt", "r"); fread(&val,4, 10, fp); writeStr(xbee,&val); fclose(fp); }Ray
If you want to dump out the contents of Sol_dat.txt you should declare a char buffer that's at least as large as the largest line in the file. Then use fgets to read the line. Your code would look something like this:
void sd_File() { char buffer[80]; fp = fopen("Sol_dat.txt", "r"); while (fgets(buffer, 80, fp)) { writeStr(xbee, buffer); } fclose(fp); }