How to read data from Arduino board to pc using C? - c

I found a tutorial for writing data to an Arduino board over here: https://salilkapur.wordpress.com/2013/03/08/communicating-with-arduino-using-c/
The code uses file = fopen("/dev/ttyUSB0","w+");to open the port for the read/write operation and uses fprintf to write data to the device. But when I tried using fscanf to retrieve the data from the Arduino (I used Serial.print for writing the data back to the PC from the Arduino end, and the data was formatted as DEC), it didn't work.
I am able to see the output using the serial monitor in the Arduino IDE but I am not able to view the output in my C program's output. Why isn't it working and what do I have to do to get it working?
The program was run in Ubuntu.
This is my C code that is supposed to run on the PC:
#include <stdio.h>
int main()
{
FILE *file;
char a=0;
file = fopen("/dev/ttyUSB0","w+");
int i = 0;
if(file == -1)
printf("error");
for(i = 0 ; i < 3 ; i++)
{
fprintf(file,"C");
fscanf(file, "%c", &a);
printf("%c", a);
}
fclose(file);
}
I also tried few variations like, using %d instead of %c, using int in place of char and using fflush. I don't know why it doesn't work. Could it be that my Arduino board doesn't work?
Note: it is supposed to give an output after every character input.

The reason you cannot read anything is that when you call
file = fopen("/dev/ttyUSB0","w+");
the arduino is reset, and it takes 1-2 seconds to boot. For some reason, the read hangs indefinetely.
Adding sleep(2); next to fopen will likely do the trick.
See how to disable auto reset

Related

Error with binary-writting mode with C, on Windows?

I am learning how to write a simple CGI page with C language. I tried with Apache on both Linux and Windows. I compiled my scripts on 2 different computers that run different OSes.
Firstly, I created a simple CGI page for getting a static plain-text content:
#include
int main()
{
FILE *fp = fopen("plain_text.txt", "r"); // text-mode only.
if (fp)
{
int ch;
printf("content-type: text/plain\n\n");
while ((ch = fgetc(fp)) != EOF)
{
printf("%c", ch);
}
fclose(fp);
}
return 0;
}
I compiled it into an executable and put it in cgi-bin directory. When I browse it with my web-browser, it returns the plain-text content correctly (both Linux and Windows).
Then, I modified above script for getting a simple JPEG content.
(I understand that: every JPEG picture is a binary file)
#include
int main()
{
FILE *fp = fopen("cat_original.jpg", "rb"); // with binary-mode.
if (fp)
{
int ch;
printf("content-type: image/jpg\n\n");
while (((ch = fgetc(fp)) != EOF) || (!feof(f1))) // can read whole content of any binary file.
{
printf("%c", ch);
}
fclose(fp);
}
return 0;
}
I compiled it into an executable and put it in cgi-bin directory, too.
I can get the correct returned-image with Linux compiled-executable files; but, the Windows does not.
To understand the problem, I downloaded the returned-image with Windows compiled-execute files.
(I named this image: cat_downloaded_windows.jpg)
Then, I used VBinDiff for compare 2 images: cat_original.jpg (68,603 bytes) and cat_downloaded_windows.jpg (68,871 bytes).
There are many lines in cat_downloaded_windows.jpg (like the row I marked) have a character which cat_original.jpg does not have.
VBinDiff
So, I guess that the Windows OS causes the problem (Windows add some characters automatically, and Linux does not)
(Apache and web-browsers do not cause problem)
So, I posted this topic into StackOverflow for getting your helps. I have 2 questions:
Is there any problem with the printf("%c", ch); (in my script) on Windows?
Is there any way to print binary content into stdout, both Linux and Windows?
I am learning programming myself, and this is the first time I ask on StakOverflow.
So, if my question is not clear, please comment below this question; I will try to explain it more.
Thank you for your time!
When you use printf() to write to standard output, it is working in text mode, not binary mode, so every time your program encounters a newline \n in the JPEG file, it writes \r\n on Windows, which corrupts the JPEG file.
You'll need to know how to put standard output into binary mode and you'll need to ensure that you generate \r\n in place of \n in the headers.
The MSDN documentation says you can use _setmode(), and shows an example (setting stdin instead of stdout):
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int result;
// Set "stdin" to have binary mode:
result = _setmode(_fileno(stdin), _O_BINARY);
if (result == -1)
perror("Cannot set mode");
else
printf("'stdin' successfully changed to binary mode\n");
}

I/O redirection

#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
for(i=1; i<=255; i++)
{
printf("%d %c\n",i,i);
}
}
Hey i am working my way out from i/o redirection, and i got stuck in outputting ascii table from command prompt i done this.
C:\New folder\practice> main.exe > temp.txt
C:\New folder\practice> type temp.txt
and after hitting enter (after type temp.txt) it only outputs first 26 numbers. My question is why?
Also can someone explain me how to just copy the code into text file using redirection I know how to do using FILE I/O.
Because you're using MS-DOS... er MS WinDOS, and there ASCII number 26/^Z is the end-of-text-file mark.
The feature exists so that the environment is compatible with the CP/M operating system of the early 1970s, in case you'd need to use some files that originate from that. As you've noticed, only type works like that, but more would display more... (no pun intended).
No kidding.
It is very dangerous to write non ASCII characters in a text stream. 0x10 is \n and and can be changed into the underlying system end of line which is \r\n on Windows.
The correct way is to open a file in binary mode:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
FILE *fd = fopen("temp.txt", "wb");
if (NULL == fd) {
perror("Error opening file");
return 1;
}
for(i=1; i<=255; i++)
{
fprintf(fd, "%d %c\n",i,i);
}
fclose(fd);
return 0;
}
That being said, commands expecting text files may stop when they read a SUB control character (CtrlZ code 0x1A), which is you current problem...

Linux fread() call to USB device freezes when exposed to high CPU utilization

Recently I've written a driver for a drawing tablet called the "Boogie Board RIP" to be able to use it as an input device for linux. It can be connected via usb to a computer. When the provided pen is near or touching the device's screen, it will send data telling where the pen is on the screen.
Basically the driver works great. I can write on it as if it was a wacom tablet.
At unpredictable times, the program will hang on the line below and the cursor on my computer screen will stay in place
fread(packet, sizeof(char), BYTES, f);
Where:
"packet" is an array of 8 bytes
"BYTES" is 8
"f" is a file opened in binary read (rb) mode. In my case it's /dev/usb/hiddev0
The basic program layout is a while loop that reads a byte at a time. Below is a mock-up of the much larger thing:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char *path = argv[1];
unsigned char packet[8];
FILE *f = fopen(path, "rb");
int i;
while (1) {
fread(packet, sizeof(char), 8, f);
for(i=0;i<8;i++) {
printf("%x", packet[i]);
fflush(stdout);
}
}
}
I started to notice that my driver would "freeze" more often when I was running more things, like watching youtube, playing music... These aren't great examples. Basically I began to suspect it was related to CPU utilization. So I wrote the program below to test it:
#include <stdio.h>
int main() {
while(1) {
printf("a");
fflush(stdout);
fflush(stdout);
fflush(stdout);
fflush(stdout);
fflush(stdout);
fflush(stdout);
fflush(stdout);
}
}
Running this "infinite loop" program in a separate terminal while running the other program above in another terminal will result in harshly more frequent freezes. Basically the program will stop at the fread() line without fail within 2 seconds.
I learned that when the call to fread() doesn't get any data I can still read from the device with another instance of that program or simply printing out the contents of the file via sudo cat /dev/usb/hiddev0. The original process remains stuck while the new program will spit out the data coming from the device.
It seems as though the file simply closes. But that doesn't make sense because then fread would segfault on the next read. Looking for any ideas.
EDIT:
I solved this by using libusb to deal with reading from my device rather than trying to read directly from the device file.

How can I verify in my C program that four terminals are currently open?

So I'm going to preface this by saying that this is for a homework project in my class. I am supposed to determine that the user opened four terminal windows before running the program, and I have to do this by determining if I can open four terminal number buffers from /dev/pts/ as read-only. I then have to save these first four buffers so I can open them again to write to the terminals. I know how to open the files with fopen but my issue is even the terminals that aren't open anymore still show up and are accessible. I know that its pretty frowned upon to ask for homework help but I've been working at this for hours and I don't want it written for me I just want some direction. How can I check that there are four terminals open using the method that I have to use? Also here's my code so maybe one of y'all can see what I'm doing wrong.
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 100
int main(){
int i, ptsNum[4], ptsCount = 0;
FILE *fp;
char ptsName[20];
for(i = 0; i < 20; i++){
// Append the terminal number to the end of the buffer name
sprintf(ptsName, "/dev/pts/%d", i);
// Try to open the file
if((fp = fopen(ptsName, "r")) != NULL){
// Save the terminal number if the buffer exists
ptsNum[ptsCount] = i;
ptsCount++;
fclose(fp);
}
}
return 0;
}
Well, you try to open the terminals, but once you get them counted, you fclose(3) them, so in case you want them open, don't do the last fclose(3) at the end of the loop.

How to stream system() command ouput to any variable

I created a C program which will run some system() commands and save the output to a .txt file in a particular folder of C drive (program is to be run on domain clients with startup privileges), from where I'll filter the data and show it on output console screen.
Everything worked fine, but I couldn't design it for those PCs who have OS installed in other drives (e.g. D:, E:, etc), since they will not have this particular folder in their C: drive. I can't write temporary .txt files anywhere else due to group policies.
Is there any method to stream this data directly into any array variable? I went through popen() function, but it would require a very large array of unpredicted size to be defined (since the output of system() command may be very large). For example, exporting the registry keys of HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall into a .txt file. Its size may be up to 50KB or bigger.
reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall C:\\..(somewhere)....\\reg_output.txt
There are some more similar commands with large output. I don't know Win API programming yet, thus I am using system command. Can there be an easy alternative to writing to .txt ?
#Megharaj!
As you used
char line[100];
fp = popen("ifconfig eth0", "r");
fgets(line, 100, fp);
I'll have to use
char reg_output[100000];
fp=popen("reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall ????","r");
fgets(line,100000,fp);
Where do I export the registry values? (Since the DOS command for exporting this needs to write it to a file), as compared to following code I am using.
Assigning a space of 100000 isn't sure that it will not be error prone. And assigning too high value also will affect the memory on startup (I'm not sure but guess so).
While using file handling I do it as:
char line[5000]; FILE* fp_reg; int ch,n=0;
system("reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall c:\\registries.txt");
fp_reg=fopen("c:\\registries.txt","r");
while((ch=fgetc(fp_reg))!=EOF)
{
if(isalnum(ch) || ch=='\n') //allow only alpha numeric & '\n' to pass to array
{ line[n]=ch;
if(ch=='\n')
{ filter_for_software(line,n); //Send the array for filtering function
n=0; // Reset the array 'line'
}
n++;
}
}
(I didn't copy the code from source, since I am sitting on a different PC. But the code is almost similar to this. Some errors may come if you copy this code & run.)
This way, I take each line from file and send it for filtering to get 'installed software's name'. How do I do it with 'popen()', so that I could pick up a line and throw it onto a function. Plz write some code also for this.
If you want to store the output in an array, you will have to allocate an array of appropriate size. There is just no way around that.
But you don't need to do that if you use popen. You get a FILE * handle and can just read the output in small parts and process it on the go.
from where I'll filter the data and show it on output console screen.
How do you do that? With the shell or in C? If in C, then you read the output of the systemed command just like you would read your txt file. The only difference is that you need to close it with pclose instead of fclose, so there are only advantages to doing it with a text file.
If in shell, then you can start the program you use with another call to popen, this time in a "w" (write) direction and write the output of one pipe as input to the other. However, in this case you could have just called a shell with an anonymous pipe in the first place. ;-)
Edit:
Your own answer makes clear that your requirements are quite different from what you think they are. There is no way to read the output of reg export back via a pipe and popen if it insists on writing to a file.
What you can try is to write a file to your temp folder; you should be allowed to create files there, otherwise Windows will not work correctly. Just specify something like "%TEMP%\reg.out" as file and read your data back from there.
If that doesn't work, you are out of luck with reg export. But you can use some Windows API function for querying the registry directly. Here is a starting point.
Alternatively, you might want to look into the possibility of employing PowerShell. This question might be of interest to you.
In linux to use the values from the system command i use popen, I am just giving an example of code that I had written some time long back, to get the ip address of the pc by system command "ifconfig eth0" to the string/a file. see the example
void get_my_ip(char *ip_mac_address)
{
FILE *fp,*output;
char *start=NULL;
char *end=NULL;
char line[100];
output=fopen("my_ip_address.txt", "w");
if(output == NULL) {
printf("error creating outputfile\n");
return -1;
}
printf("program to self query the ip address\n");
fp = popen("ifconfig eth0", "r");
fgets(line, 100, fp);
start=strstr(line, CHECK_STRING_MAC);
start = start + 7;
fwrite(start, 1, 17, output); start = NULL;
fgets(line, 100, fp);
start=strstr(line, CHECK_STRING_IP);
start = start + 10;
fwrite(start, 1, 14, output);
fclose(output);
pclose(fp);
if( access("my_ip_address.txt", F_OK ) != -1 ) {
printf("found file having ip address\n");
output=fopen("my_ip_address.txt", "r");
fgets(ip_mac_address, 32, output);
}
else
printf("unabe to find file with ip address\n");
fclose(output);
printf("my ip and mac address adress is %s \n",ip_mac_address);
}
You can create a temporary file using some API from Windows, and store your data in it.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875(v=vs.85).aspx
There is a C++ example in the link, you should be able to adapt it to your case.
So, I prepared the code to stream the output of a DOS command to a file pointer in read mode and check it line by line:
char array_sys[200]; FILE *fp_sys; int ch,n=0;
fp=popen("systeminfo","r"); //runs a DOS command & read it with a file pointer
if(fp_sys==NULL) printf("can't open file\n");
while((ch=fgetc(fp_sys))!=EOF) //READ CHARACTERS FROM FILE POINTER UNTIL FILE ENDS
{
array_sys[n]=ch; //ASSIGN CH TO EACH ELEMENT OF ARRAY
n++; //INCREMENT ELEMENTS OF ARRAY:-arr_sys
if(ch=='\n') //IF ELEMENTS MEET A NEW LINE CHARACTER
{
disp_date(array_sys,n); //PASS ARRAY TO FUNCTION:-disp_date
n=0; //RESET THE ARRAY
}
}
Now this is how I process array in function to get the name of operating system.
void disp_date(char array_sys[],int ind)
{
char os_name[9]={"OS Name:"};
if(strstr(array_sys,os_name)) //IF 'OS NAME' IS PRESENT IN ARRAY
{
printf("%s",array_sys); //PRINT THE ARRAY
}
}

Resources