Pages: [1]   Go Down
Author Topic: How to read from serial in c ? (under linux)  (Read 1155 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Like title says...my arduino board periodically sends some integers througth serial board.
I have a controller thread written in C and I need to read these integers. I'm programming under linux so "everything's a file", so I guess I just have to open serial for reading...but how to know if I'm reading the same integer or a new one?
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 287
Posts: 25682
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When you're reading a line of text, how do you know it's a new word, and not the same one?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Austin, TX
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6106
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

https://www.google.com/search?q=linux+c+read+serial+port
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Does this work in kernel mode too? I'm writing a kernel module which has to interact with arduino board..
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Does this work in kernel mode too? I'm writing a kernel module which has to interact with arduino board..

Why don't you try it? Just
Code:
FILE* ardport = fopen("/dev/ttyACM0", "r+");
FILE* output = fopen("/tmp/ardoutput", "a");

int c;
while ((c = fgetc(ardport)) != EOF) {
  fputc(output, c);
}
fclose(ardport);
flose(output);
Logged

UK
Offline Offline
Shannon Member
****
Karma: 222
Posts: 12524
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

how to know if I'm reading the same integer or a new one?

You wrote the program that is sending them, so send them in a way that lets your receiving code detect the boundary between numbers. For example, if you're sending the numbers as an ASCII sequence of decimal digits, you could use any non-digit character(s) as a separator. Comma and/or a line feed would be obvious candidates.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Finland
Offline Offline
Sr. Member
****
Karma: 1
Posts: 270
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you are sending integers only, it may be easiest to send them as binary data,  though there are still some quirks you have to take care of:
- Check if the Arduino and your Linux computer share the same byte order (little endian vs. big endian). If not, you need to convert to/from the network byte order when sending/receiving the integers. (Check htons/ntohs man pages on Linux).
- "int" is 16 bits on the Arduino and probably 32 bits on your Linux computer.  Use "short" on Linux instead.
« Last Edit: October 29, 2012, 07:36:17 am by pekkaa » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks guys I think I figured out the way! smiley

Now I have a bigger problem anyway...in my kernel module the open() function is not recognized, it gives me "implicit declaration"!
My include part is:

Code:
#include <linux/module.h>
#include <linux/unistd.h>
#include <asm/io.h>
#include <asm/fcntl.h>
#define SERIAL_PORT "/dev/ttyACM0"

while the error is in this line:
Code:
void myfun(void){
  int fd = open(SERIAL_PORT,O_RDONLY | O_NOCTTY);
  ..reading...

can you help me to solve this?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
it gives me "implicit declaration"!
I'm nearly certain there was more to the message than that.
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 108
Posts: 5144
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Does this work in kernel mode too? I'm writing a kernel module which has to interact with arduino board..

You don't know how to access a serial interface in Linux but you wanna write a kernel module?

Start with a smaller project, build a simple kernel module. Extend it to read files. Extend it to access simple character devices (like /dev/random). If that all works try accessing a complex tty device like the serial interface.
You cannot use functionality of the GNU C library withing the kernel (fopen, fclose and the like), don't use any library at all, use the kernel calls directly. This is really different from userland programming.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've done it..normal kernel module works and I know I cannot use gnu c library, if you look at the code I'm not using it at all.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tried with a normal user space program and still does not work: a lot of strange characters come out.
I see a problem in your code too: you do not set baud rate at all, I think this has to be a problem...
Logged

Finland
Offline Offline
Sr. Member
****
Karma: 1
Posts: 270
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tried with a normal user space program and still does not work: a lot of strange characters come out.
I see a problem in your code too: you do not set baud rate at all, I think this has to be a problem...

Yes, you obviously have to set the baud rate and possibly other tty parameters. You can use stty from the command line before running the program or cfsetspeed function in your program.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying this way but still no success:
Code:
        struct termios options;
int nBytesRead = 0;
char buffer[20];

int fd = open(SERIAL_PORT,O_RDONLY | O_NOCTTY);

if(fd == -1){
perror("unable to open serial port");
return -1;
}

       //setting baud rate
tcgetattr(fd, &options);
cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
options.c_cflag |= (CLOCAL | CREAD);
tcsetattr(fd,TCSANOW,&options);
fcntl(fd,F_SETFL,0); //setting blocking read

nBytesRead = read(fd,buffer,20);
now it just immediately returns from read with 0 bytes read...but read() should be blocking.
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 108
Posts: 5144
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You haven't told the tty after how many characters it should return from a blocking call:

Code:
options.c_cc[VMIN] = 20; // block until 20 characters are read

This topic gets very Linux specific, don't you think you should ask your questions on a Linux forum? Your questions have nothing to do with the Arduino platform.
Logged

Pages: [1]   Go Up
Jump to: