Slovakia
Offline
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« on: January 30, 2011, 01:21:46 pm » |
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: 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: #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)
Offline
Brattain Member
Karma: 279
Posts: 15314
Measurement changes behavior
|
 |
« Reply #1 on: January 30, 2011, 01:31:01 pm » |
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
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #2 on: January 30, 2011, 02:16:10 pm » |
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
God Member
Karma: 20
Posts: 717
Firefox & Arduino rocks
|
 |
« Reply #3 on: January 30, 2011, 02:22:36 pm » |
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
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #4 on: January 30, 2011, 03:45:35 pm » |
write(fd, 1, sizeof(int)); //send data How big is an int on your PC? 4 btyes, probably. 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
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #5 on: January 31, 2011, 04:21:35 am » |
smeezekitty: Thanks for finding this mistake  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: write(fd, 1, 4); //send data Again the whole code: PC side: #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: 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
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #6 on: January 31, 2011, 06:03:51 am » |
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
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #7 on: January 31, 2011, 10:29:59 am » |
Excuse me, I don't understand the last sentence. 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
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #8 on: January 31, 2011, 10:51:07 am » |
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
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #9 on: January 31, 2011, 10:52:56 am » |
Thanks, now I understand. And please, could you suggest me a solution?
|
|
|
|
|
Logged
|
|
|
|
|
Slovakia
Offline
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #10 on: February 02, 2011, 11:08:33 am » |
If I understand, I'm supposed to sleep() my PC program for a while, is that right? I tried, but without success. #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
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #11 on: February 02, 2011, 03:14:17 pm » |
I tried, but without success. Is that sleep() for one second, or one millisecond? One millisecond is nowhere near long enough.
|
|
|
|
|
Logged
|
|
|
|
|
Washington
Offline
God Member
Karma: 20
Posts: 717
Firefox & Arduino rocks
|
 |
« Reply #12 on: February 02, 2011, 04:03:32 pm » |
|
|
|
|
|
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
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #13 on: February 03, 2011, 03:29:29 pm » |
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
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #14 on: February 05, 2011, 05:45:34 am » |
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: void setup() { Serial.begin(9600); }
void loop() { Serial.write(1); } PC 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: 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
|
|
|
|
|
|