Pages: [1]   Go Down
Author Topic: Communication between Arduino and PC  (Read 1438 times)
0 Members and 1 Guest are viewing this topic.
Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi there!

I'm trying to make a program for communication between my Arduino and the PC. I need to be able to send and receive data on the both sides. I've already written some code and the Arduino receives some bytes, but I actually don't know in which form, because the following code doesn't work properly.

Arduino side:
Code:
const int ledPin = 12;


void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
    if (Serial.available())
    {
       if (Serial.read() ==  1)
       {
         digitalWrite(ledPin, HIGH);
       }
    }

Code for the PC application:
Code:
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>

int open_port(void)
{
int fd; //file description for the serial port

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1)
{
printf("open_port: Unable to open /dev/ttyUSB0! \n");
}
else
{
fcntl(fd, F_SETFL, 0);
printf("open_port: Opening port /dev/ttyUSB0 successful! \n");
}

return fd;
}

int configure_port(int fd)
{
struct termios port_settings; //structure to store the port settings in

cfsetispeed(&port_settings, B115200); //set baud rates
cfsetospeed(&port_settings, B115200);

port_settings.c_cflag &= ~PARENB; //set no parity
port_settings.c_cflag &= ~CSTOPB; //stop bits, data bits
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;

tcsetattr(fd, TCSANOW, &port_settings); //aply the settings to the port
return fd;
}

int query_modem(int fd)
{
char n;
fd_set rdfs;
struct timeval timeout;

char buffer;

//initialise the timeout structure
timeout.tv_sec = 10; //number of timeout secs
timeout.tv_usec = 0;

write(fd, 1, sizeof(int)); //send data
printf("Wrote.\n");

return 0;
}

int main()
{
int fd = open_port();
configure_port(fd);
query_modem(fd);

return 0;
}

I would be really appreciated for any help.
Logged

Left Coast, CA (USA)
Online Online
Brattain Member
*****
Karma: 331
Posts: 16514
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can't say anything on the PC side as I'm not that good at PC programming. However on your Arduino side your code seems to wait for a '1' character and turns on the led. It will then stay on forever no matter what other characters you receive. Was that your intentions? Perhaps a else clause added to the second if statement to turn off the led if any character other then a '1' is received?

Lefty
Logged

Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yea, it actually was my intention, because I'm just testing. It's not a serious application, it's just testing for further work. But thanks for replying.
Logged

Washington
Offline Offline
God Member
*****
Karma: 30
Posts: 779
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
cfsetispeed(&port_settings, B115200); //set baud rates
cfsetospeed(&port_settings, B115200);
115200 != 9600
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

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

Code:
write(fd, 1, sizeof(int)); //send data
How big is an int on your PC? 4 btyes, probably.

Code:
       if (Serial.read() ==  1)
Look at the return code and description for the Serial.read function. The return type is int, but that's because there is a need to return a invalid call value (when there is no data to read), but all values in the range of 0 to 255 (a byte, which is what Serial.read() actually reads) are valid, so none of them can be used to indicate invalid data. So, Serial.read() returns an int, but if the value is not -1, the actual value returned is a byte (one and only one byte).

So, you are not reading as much data, in the same way, as you are writing.
Logged

Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

smeezekitty: Thanks for finding this mistake  smiley
Paul: Yes, but my intention was not to test invalid data read, but to send number "1" and then test whether number "1" was received.

I think the problem should be in this line on the PC side:
Code:
write(fd, 1, 4); //send data

Again the whole code:
PC side:
Code:
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>

int open_port(void)
{
int fd; //file description for the serial port

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1)
{
printf("open_port: Unable to open /dev/ttyUSB0! \n");
}
else
{
fcntl(fd, F_SETFL, 0);
printf("open_port: Opening port /dev/ttyUSB0 successful! \n");
}

return fd;
}

int configure_port(int fd)
{
struct termios port_settings; //structure to store the port settings in

cfsetispeed(&port_settings, B9600); //set baud rates
cfsetospeed(&port_settings, B9600);

port_settings.c_cflag &= ~PARENB; //set no parity
port_settings.c_cflag &= ~CSTOPB; //stop bits, data bits
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;

tcsetattr(fd, TCSANOW, &port_settings); //aply the settings to the port
return fd;
}

int query_modem(int fd)
{
char n;
fd_set rdfs;
struct timeval timeout;

char buffer;

//initialise the timeout structure
timeout.tv_sec = 10; //number of timeout secs
timeout.tv_usec = 0;

write(fd, 1, 4); //send data
printf("Wrote.\n");

n = select(fd+1, &rdfs, NULL, NULL, &timeout);

if (n < 0)
{
printf("Select failed.\n");
}
else if (n == 0)
{
printf("Timeout!\n");
}
else
{
printf("Bytes detected on the port!\n");
}

return 0;
}

int main()
{
int fd = open_port();
configure_port(fd);
query_modem(fd);

return 0;
}

Arduino side:
Code:
const int ledPin = 12;
int incomingByte = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
    if (Serial.available())
    {
       incomingByte = Serial.read();
       Serial.println(incomingByte, DEC);
       digitalWrite(ledPin, HIGH);
    }
   
}

The aim of this code is following: The PC application sends the number "1" to the port and waits for receiving the same number back. The Arduino application reads what comes on this port and then sends it back (and lights a LED). But the result - the PC application sends the byte, but Arduino doesn't receives it, because it doesn't sends it back and neither lights the LED.
Logged

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

On the PC, you open the serial port. This causes the Arduino to reset. It takes the Arduino (more than) a few milliseconds to boot up and establish serial communications.

Meanwhile, you've jammed a character down the serial port, seen that no reply was received, and quit.

In the setup() function, have the Arduino send a message. Have the PC application wait for that message, and then send some data to the Arduino. Does that work?
Logged

Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Excuse me, I don't understand the last sentence.
Quote
In the setup() function, have the Arduino send a message. Have the PC application wait for that message, and then send some data to the Arduino. Does that work?
Could you explain to to me please?
Logged

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

Quote
I don't understand the last sentence.
Think about how a telephone works. If you want to call someone, and ask a question, you don't dial the number and start speaking right away, then hang up when you don't get a response.

You dial the number ( open the serial connection) and wait for the person to answer and say hello. Then, you ask your question or make your statement.

You are not currently waiting for the Arduino to say hello.
Logged

Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, now I understand. And please, could you suggest me a solution?
Logged

Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If I understand, I'm supposed to sleep() my PC program for a while, is that right?

I tried, but without success.

Code:
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>

int open_port(void)
{
int fd; //file description for the serial port

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1)
{
printf("open_port: Unable to open /dev/ttyUSB0! \n");
}
else
{
fcntl(fd, F_SETFL, 0);
printf("open_port: Opening port /dev/ttyUSB0 successful! \n");
}

return fd;
}

int configure_port(int fd)
{
struct termios port_settings; //structure to store the port settings in

cfsetispeed(&port_settings, B9600); //set baud rates
cfsetospeed(&port_settings, B9600);

port_settings.c_cflag &= ~PARENB; //set no parity
port_settings.c_cflag &= ~CSTOPB; //stop bits, data bits
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;

tcsetattr(fd, TCSANOW, &port_settings); //aply the settings to the port
return fd;
}

int query_modem(int fd)
{
char n;
fd_set rdfs;
struct timeval timeout;

char buffer;

//initialise the timeout structure
timeout.tv_sec = 10; //number of timeout secs
timeout.tv_usec = 0;

write(fd, 1, 4); //send data
printf("Wrote.\n");

sleep(1);

n = select(fd+1, &rdfs, NULL, NULL, &timeout);

if (n < 0)
{
printf("Select failed.\n");
}
else if (n == 0)
{
printf("Timeout!\n");
}
else
{
printf("Bytes detected on the port!\n");
}

return 0;
}

int main()
{
int fd = open_port();
configure_port(fd);
query_modem(fd);

return 0;
}
Logged

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

Quote
I tried, but without success.
Is that sleep() for one second, or one millisecond? One millisecond is nowhere near long enough.
Logged

Washington
Offline Offline
God Member
*****
Karma: 30
Posts: 779
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I tried, but without success.
Is that sleep() for one second, or one millisecond? One millisecond is nowhere near long enough.

One second. I think it should be enough.
Logged

Slovakia
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay, I tried something else - sending bytes from arduino to PC. It looks quite good, but one small problem - always the 10th time I read data, I get another data as I expect.

Arduino code:
Code:
void setup()
{
  Serial.begin(9600);
}

void loop()
{
       Serial.write(1);
}

PC code:
Code:
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>

int open_port(void)
{
int fd; //file description for the serial port

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1)
{
printf("open_port: Unable to open /dev/ttyUSB0! \n");
}
else
{
fcntl(fd, F_SETFL, 0);
printf("open_port: Opening port /dev/ttyUSB0 successful! \n");
}

return fd;
}

int configure_port(int fd)
{
struct termios port_settings; //structure to store the port settings in

cfsetispeed(&port_settings, B9600); //set baud rates
cfsetospeed(&port_settings, B9600);

port_settings.c_cflag &= ~PARENB; //set no parity
port_settings.c_cflag &= ~CSTOPB; //stop bits, data bits
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;

tcsetattr(fd, TCSANOW, &port_settings); //aply the settings to the port
return fd;
}

int main()
{
int fd = open_port();
configure_port(fd);

fd_set rdfs;
struct timeval timeout;
char incoming;
int i;

//initialise the timeout structure
timeout.tv_sec = 10; //number of timeout secs
timeout.tv_usec = 0;

sleep(2);
for (i = 0; i < 30; i++)
{
read(fd, &incoming, sizeof(char));
printf("I: %d\tGOT %d.\n", i, (int)incoming);
sleep(1);
}

return 0;
}

And the result:
Code:
I: 0 GOT 1.
I: 1 GOT 1.
I: 2 GOT 1.
I: 3 GOT 1.
I: 4 GOT 1.
I: 5 GOT 1.
I: 6 GOT 1.
I: 7 GOT 1.
I: 8 GOT 1.
I: 9 GOT 97.
I: 10 GOT 1.
I: 11 GOT 1.
I: 12 GOT 1.
I: 13 GOT 1.
I: 14 GOT 1.
I: 15 GOT 1.
I: 16 GOT 1.
I: 17 GOT 1.
I: 18 GOT 1.
I: 19 GOT 1.
I: 20 GOT 1.
I: 21 GOT 1.
I: 22 GOT 1.
I: 23 GOT 1.
I: 24 GOT 1.
I: 25 GOT 1.
I: 26 GOT 1.
I: 27 GOT 1.
I: 28 GOT 1.
I: 29 GOT 1.
As you can see, the program is always supposed to read number 1, but in the tenth case (i = 9) I get 97. And it's not random, I always get wrong data (sometimes another numbers) in the tenth case. Am I doing a mistake somewhere?
Logged

Pages: [1]   Go Up
Jump to: