I am working on a quadcopter project with Beaglebone.
I need help with using pwm on Beaglebone through a C program.
I have attached the following code,
#include <stdio.h>
#include <string.h>
#include <unistd.h>
struct pwm
{
char period[100];
char duty[100];
char polarity[100];
char run[100];
}pwm1,pwm2,pwm3,pwm4;
char pwm_1[]="P9_21";
char pwm_2[]="P9_14";
char pwm_3[]="P8_13";
char pwm_4[]="P9_42";
int initialize(struct pwm &pwmi, char pwm_i[])
{
sprintf(path,"echo \"bone_pwm_%s\" >> /sys/devices/bone_capemgr.9/slots",pwm_i);
fp = popen(path,"r");
fflush(fp);
usleep(1000);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/period",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.period,path);
fflush(fp);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/duty",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.duty,path);
fflush(fp);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/polarity",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.polarity,path);
fflush(fp);
sprintf(path,"ls /sys/devices/ocp.3/pwm_test_%s.*/run",pwm_i);
fp = popen(path,"r");
while(fgets(path,100,fp)!=NULL)
strcpy(pwmi.run,path);
fflush(fp);
pclose(fp);
return 0;
printf("%s%s%s%s",pwmi.period,pwmi.duty,pwmi.polarity,pwmi.run)
}
int pwmperiod(struct pwm &pwmi, unsigned int period)
{
sprintf(path,"echo %d > %s", period, pwm.period);
fp = popen(path,"r");
usleep(1000);
pclose(fp);
return 0;
}
int main()
{
unsigned int period = 200000;
initialize(pwm1,pwm_1);
initialize(pwm2,pwm_2);
initialize(pwm3,pwm_3);
initialize(pwm4,pwm_4);
pwmperiod(pwm1,period);
return 0;
}
Now the above code works perfectly fine. But I want to use the pwmperiod() function a little differently. Instead of using popen() all the way, I want to use fopen() and fprintf() for the function pwmperiod() . Something like this,
int pwmperiod(struct pwm &pwmi, unsigned int period)
{
fp = fopen(pwmi.period,"r+");
fseek(fp,0,SEEK_SET);
fprintf(fp,"%d",period);
fclose(fp);
return 0;
}
I tried the modified code but when it attempts to write the period value, it outputs "segmentation fault".
I realized that fopen() takes a const char while pwmi.period is just char. Another problem popen() and sprint() are not compatible with const char.
So is there a way to resolve the conversion?
Also how often is popen() used in C/C++ programs?
PS:
Not an expert coder and I am not from a computer science background. I am learning progressively.
Again, the code works with popen() perfectly. But then I am comfortable with file handling in C. So I would prefer personally fopen() over popen() . Moreover I feel it would be pointless to use popen() in C. Might as well use a shell script for pwm.
Leaving aside for a moment the issue of char* vs. const char* (since a char* can anyway be passed to any function taking a const char*).
Have you checked that the return value from fopen is non-NULL?
Note that the file must exist when fopen is called with r+. If it doesn't, fopen will return NULL, generating a segfault.
Since the file is only being written, not read, consider using
fp = fopen(pwmi.period,"w");
which will create a new file if one doesn't already exist.
Related
I have no idea why this does not work:
#include <stdio.h>
int main(){
FILE* fp = fopen("txt2","wr");
if(!fp) return 1;
fprintf(fp,"20");
fseek(fp,0,SEEK_SET);
fprintf(fp,"19");
rewind(fp);
char c;
while((c=fgetc(fp))!=EOF)
printf("%c",c);
}
Here should be write 20, then rewrite to 19, set the position to start of file, and the read the char till EOF (so should print 19). But prints nothing. Why is that?
I have tried to make better check for return poitner to fp (because of wr):
EDIT:
#include <stdio.h>
int main(){
FILE *fp = fopen("txt","wr");
if(!fp){
printf("nada\n");
return 1;
}
}
But it compiles without problem. Why is that? The wr should be UB (and thus cause segfault or another err) or?
The mode "wr" is not valid string for POSIX fopen() or Microsoft fopen(). You probably want to use "w+". Using "r+" would be an alternative, but then the file must exist before you open it.
The implementation of fopen() that you're using probably treats "wr" as equivalent to "w" (unless it reports an error and your program exits — it is a good idea to report why you are exiting). You can't read from a write-only file stream.
Strictly, you should also use int and not char for the variable c because fgetc() returns an int.
I am trying to write a function to read an input from a separate file in C, and arrange this data for further processing. I am, however, running into a segmentation fault when i am trying to assign values to int variables.
The code looks like this:
void read_file1 (char *filename, int *numTrees)
{
int tempNum;
char tempStr[1000];
char line;
FILE *filer;
filer = fopen(filename, "r");
fgets(tempStr, 1000, filer);
sscanf(tempStr, "numTrees: %i numLeaves: %i", numTrees, &tempNum);
/*
More Code
*/
}
void read_file2 (char *filename, int *numTrees, int *numLeaves)
{
char tempStr[1000];
char line;
FILE *filer;
filer = fopen(filename, "r");
fgets(tempStr, 1000, filer);
sscanf(tempStr, "numTrees: %i numLeaves: %i", numTrees, numLeaves); //Segmentation fault occurs here
/*
More Code
*/
}
int main()
{
char *filename = "datainput.txt";
int *numTrees, *numLeaves;
read_file2(filename, numTrees, numLeaves);
return 0;
}
The two different read_file functions are meant to arrange the data in different formats. The read_file1 functions works as intended, yet when i try to use a largely identical setup in read_file2, i get a segmentation fault from the sscanf. The problem seems to lie with the assignment of a value to numTrees, as attempting to assign a value separately also triggers a segmentation fault.
Which is strange, seeing as the nearly identical read_file1 works fine.
Can anyone tell the issue that is causing the error?
At least this is wrong in your code (a very common beginner's error):
int *numTrees, *numLeaves; // those pointers are not initialized
read_file2(filename, numTrees, numLeaves);
instead you want this:
int numTrees, numLeaves;
read_file2(filename, &numTrees, &numLeaves); // provide the pointers
// to the int variables
// numTrees and numLeaves
Also a check for fopen is mandatory:
filer = fopen(filename, "r");
if (filer == NULL)
{
printf("Fatal erorr, file does not exist\n");
exit(1);
}
This will abort program if the files not not exist. In real world programs a more sophisticated error handling should be done, but here at least we eliminate the chance of reading from an invalid FILE pointer.
Trying my hand at writing some C scripts, I have some code that should save a string to a file before rebooting the system. Both work separately but trying to write to file immediately before rebooting fails...
int writeToConfFile(char* filename, char* newConf) {
FILE *fp;
int status;
fp = fopen(filename, "w");
fprintf(fp,"%s",&newConf[0]);
status = fclose(fp);
return status;
}
int main(int argc, char **argv){
char extraString[1024];
strcpy(extraString,"0");
writeToConfFile("/etc/filename", extraString);
reboot(RB_AUTOBOOT);
}
adding sleep(10) between writeToConfFile and reboot does the trick, but I would like to do it in a neater way.
edit: the os is a heavily customized legacy debian.
edit2: tried changing writeToConfFile to end like this:
fp = fopen(filename, "w");
fprintf(fp,"%s",&newConf[0]);
fflush(fp);
status = fclose(fp);
return status;
but it didn't work either
As mathieu and jamieguinan suggested, calling sync() before reboot makes sure changes are written to disk
so the code ends thus:
writeToConfFile("/etc/filename", extraString);
sync();
reboot(RB_AUTOBOOT);
I have looked all over google and I find how to change in the bash config files, but my project requires a built in command to change the prompt.
I declared char pointer outside any function, my command modifies it, but when the function returns (int to continue a do while loop) and the prompt is displayed again, it is blank.
I have tried using a structure, union, and even a second char pointer and got the same issue.
I thought using a global char pointer that could be accessed and modified in any function would be the solution to this part of my project.
I would appreciate and will try any response.
Edit:
posted on my phone, tried to ask w/o code, but here it is
Code:
char *prmpt;
...
int main(int argc, char **argv)
prmpt="$$ ";
do
{
printf("%s ", prmpt);
}while(1)
int cmd_prompt(char **args)
{
prmpt = (char*)args[1];
return 1;
}
Essentially one needs to use fgets or getline or better yet they might use readline or editline. Here is an example using getline:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *prompt;
size_t len = 256;
size_t i = 0;
if (!(prompt = malloc(256 * sizeof(char))))
return 1;
strcpy(prompt, "$");
while ( 1 )
{
printf("[[%s]] ", prompt);
i = getline(&prompt, &len, stdin);
prompt[i-1] = '\0';
}
}
Or if you might try implementing getline on your own using getchar ( perhaps if getline is not available on your system, or you just want to know how it works). And eventually move on to writing your own editline library if you continue to be interested in writing shells.
I'm testing tmpfile() with mingw-gcc (CodeBlocks, latest) and program works as expected: opens 10 temp files, write 10 random strings, then read-back those 10 strings and close each *fp.
Like I said, works as expected but reading some articles about temporarily locations on win7, I begun to search where actually the files are stored, before auto-erase. On UNIX, the default location would be /tmp
On windows 7, I'm running out of ideas...
- the program folder
- the user/appdata/local/tmp/
- windows/temp
I cannot find those files and I searched even with total commander from some known strings inside. None. Any idea?
I've had the same question, and after reviewing the thread linked here:
http://sourceforge.net/p/mingw/bugs/666/
... I think the MinGW guys rolled a special version that keeps the temporary file entirely in memory.
I don't know how complete their solution is without combing through MinGW's source and/or asking on the mailing lists. In either case, it is probably a better idea to use some function other than tmpfile() anyway, given its problems.
I used Process Explorer to monitor the open handles on this program:
#include <stdio.h>
int main(int argc, char *argv[]) {
int a;
scanf("%d", &a);
printf("%p", tmpfile());
scanf("%d", &a);
return 0;
}
After printf("%p", tmpfile()); was executed, a new file handle was opened, and the file path was C:\Users\sashoalm\AppData\Local\VirtualStore\t9mc. I ran the program again and this time it was C:\Users\sashoalm\AppData\Local\VirtualStore\t728. So it places them in C:\Users\sashoalm\AppData\Local\VirtualStore\, and the name is some randomly generated string starting with "t".
See Why do files get placed in "C:\Users\<username>AppData\Local\VirtualStore\Program Files(x86)"? about the "Virtual Store" folder.
/ I tested Dev-C++ 5.11 (Mngv) gcc, and dont work. With Borland 5.5 in Code:: Block no problem.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[]) {
char filename[L_tmpnam];
char *strs[] = {"Hello\n","Goodbye\n","Cat\n","Dog\n",NULL};
char **mover = strs;
char line[80],command[80];
FILE *fp;
fp = tmpfile();
for(; *mover != NULL; mover++) fputs(*mover,fp);
rewind(fp);
while(fgets(line,80,fp))printf("%s",line);
fclose(fp);
if(tmpnam(filename) == NULL){
printf("Could not get non-conflicting file name\n");
exit(EXIT_FAILURE);
}
printf("\nFilename obtained is: %s\n\n",filename);
fp = fopen(filename, "w+");
for(mover = strs; *mover != NULL; mover++) fputs(*mover, fp);
rewind(fp);
while(fgets(line,80,fp)) printf("%s",line);
putchar('\n');
fclose(fp);
return 0;
}