1

I'm trying to connect to an arduino Mega At2560 unit connected via usb serial port in my linux based PC. Using C code, I'm trying to send and receive simple text strings, just I'm able to send and receive on both sides.

On arduino:

int incomingByte = 0; // for incoming serial data
void setup() {
 Serial.begin(19200); // opens serial port, sets data rate to 9600 bps
}
void loop() {
 // send data only when you receive data:
 if (Serial.available() > 0) {
 // read the incoming byte:
 incomingByte = Serial.read();
 // say what you got:
 Serial.print((char)incomingByte);
 }
}

basically just a loop that checks if there is serial data, and if so reads it and prints it back. there's a (char) conversion so I'll see right away the sent data is what I got back (linux side)

For the linux code I use the pretty standard code for opening a port which I found here

I call the Arduino "Table" as it will eventually operate a moving table through USB commands.

C file:

#include "TableFunctions.h"
bool connected=false;
int fd;
char *portname;
int set_interface_attribs (int fd, int speed, int parity)
{
 connected=false;
 struct termios tty;
 struct termios tty_old;
 memset(&tty, 0, sizeof tty);
 if (tcgetattr (fd, &tty) != 0)
 {
 printf("PC: Error %d from tcgetattr \n", errno);
 return -1;
 }
 tty_old = tty;
 cfsetospeed (&tty, (speed_t)B19200);
 cfsetispeed (&tty, (speed_t)B19200);
 //tty.c_cflag |= B19200;
 tty.c_cflag &= ~PARENB; // Make 8n1
 tty.c_cflag &= ~CSTOPB;
 tty.c_cflag &= ~CSIZE;
 tty.c_cflag |= CS8;
 tty.c_cflag &= ~CRTSCTS; // no flow control
 tty.c_cc[VMIN] = 1; // read doesn't block
 tty.c_cc[VTIME] = 5; // 
 tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
 cfmakeraw(&tty);
 tcflush( fd, TCIFLUSH );
 if (tcsetattr (fd, TCSANOW, &tty) != 0)
 {
 printf("PC: Error %d from tcsetattr \n", errno);
 return -1;
 }
 return 0;
}
void set_blocking(int fd, int should_block)
{
 struct termios tty;
 memset(&tty, 0, sizeof tty);
 if (tcgetattr (fd, &tty) != 0)
 {
 printf("PC: Error %d from tggetattr \n", errno);
 return;
 }
 tty.c_cc[VMIN] = should_block ? 1 : 0;
 tty.c_cc[VTIME] = 10; // 0.5 seconds read timeout
 if (tcsetattr (fd, TCSANOW, &tty) != 0)
 printf("PC: Error %d setting term attributes \n", errno);
}
void OpenSerialPort()
{
 char *portname = "/dev/ttyACM0";
 printf("PC: Opening port to table \n");
 int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
 usleep(2000000);
 if (fd < 0)
 {
 printf("PC: Error %d opening %s: %s \n", errno, portname, strerror(errno));
 return;
 }
 set_interface_attribs(fd, B19200, 0); // set speed to 19,200 bps, 8n1 (no parity)
 set_blocking(fd, 0); // set no blocking
 printf("PC: Connected\n");
 connected = true;
}
void PrepareWriteCommand(int numberOfCommands, const char *commands[numberOfCommands])
{
 if(connected) //check if arduino still connected
 {
 for(int i = 0; i<numberOfCommands; i++) //go through commands 
 {
 int bufferSize = strlen(commands[i]); //get the buffer size needed for this command
 char charArray[bufferSize]; //helper char array
 memcpy(charArray,commands[i],bufferSize);//copy command to the char array
 charArray[bufferSize]=0; //make sure there is a stop symbok at the end
 WriteSerialPort(charArray); //command is ready to be sent, send it.
 }
 }
}
int WriteSerialPort(const char *buffer)
{
 printf("PC: Now writing: ");
 int n_written = 0; //how many bytes were written
 n_written = write(fd, buffer, strlen(buffer)); //write the command and return how many bytes were written
 printf("\n");
 //check bytes send and return ouput (error, nothing or x bytes sent)
 if(n_written<0)
 {
 printf("PC: Error %d from %s \n",errno, strerror(errno));
 }
 else if(n_written == 0)
 {
 printf("PC: Nothing was written \n");
 }
 else
 {
 printf("PC: Written %i bytes \n", n_written);
 }
}
int ReadSerialPort(char *buffer, unsigned int buff_size)
{
 //check if arduino still connected
 if(connected)
 {
 //read the serial data
 if(read(fd,buffer,buff_size))
 return sizeof(buffer); //return how much bytes were read
 else
 {
 //else print nothing received
 printf("PC: Arduino not Connected (ReadSerialPort) \n");
 }
 }
}

in OpenSerialPort I basically open a new fd, and call the functions that set the communication settings. I use PrepareWriteCommand to make sure commands input from users are with a stop symbol and send them to WriteSerialPort where I use write() and print how many bytes were sent.

H file:

#include <errno.h>
#include <fcntl.h> 
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#define MAX_DATA_LENGTH 256
int set_interface_attribs (int fd, int speed, int parity);
void set_blocking(int fd, int should_block);
void OpenSerialPort();
void PrepareWriteCommand(int numberOfCommands, const char *commands[numberOfCommands]);
int WriteSerialPort(const char *buffer);
int ReadSerialPort(char *buffer, unsigned int buff_size);

Main:

#include "TableFunctions.h"
#include <stdio.h>
#include <stdlib.h> 
int main(int argc, char *argv[])
 {
 char output[MAX_DATA_LENGTH]; //char array to hold arduino output
 int received = 0; // check if read() got any bytes
 const char* commands[]={"test"}; //test command
 OpenSerialPort(); // open serial port
 PrepareWriteCommand((sizeof(commands)/sizeof(commands[1])),commands); //prepare command for sending
 usleep(500000); //wait for arduino response
 while(true)
 {
 ReadSerialPort(output,MAX_DATA_LENGTH);//check serial port for response
 if(strlen(output)>0) //if anything received
 {
 printf("PC: received %i\n",received); //if yes, how many bytes
 printf("PC: %s\n",output); //and what was received
 usleep(500000);
 }
 else if(strlen(output)<=0) //else print nothing received
 {
 printf("PC: Nothing received\n");
 }
 }
 return 0; //finish program
 }

I tried tweaking the tty flags settings with no success. Each time I run the C code I see the arduino resets (and after opening a new fd I give it some time for bootloading) but no communication is sent between the two.

Output:

PC: Opening port to table 
PC: Connected
testPC: Now writing: 
PC: Written 4 bytes 
PC: received 0
PC: 

Any help with understanding why the C code can't communicate with the Arduino will be highly appreciated!

asked Jan 14, 2019 at 11:35
13
  • 1
    Yes, but you can't use a parameter to set the size of a parameter. It makes no sense. You should be using const char **commands or const char *commands[] since you are using an array of pointers. Commented Jan 14, 2019 at 12:18
  • 1
    regarding: ReadSerialPort(output,MAX_DATA_LENGTH); I doubt that the function: ReadSerialPort() terminates the input with a NUL byte, so any following calls that are expecting a NUL terminated array of characters will not work. I would expect that function returns a count of the number of characters read, which can be used to insert a NUL byte into the array output[] Commented Jan 15, 2019 at 7:16
  • 1
    regarding: ReadSerialPort(output,MAX_DATA_LENGTH); The posted code does not check the returned value from ReadSerialPort() AND the actual function: ReadSerialPort() fails to return an error status when (for instance) the port is not connected Commented Jan 15, 2019 at 7:22
  • 1
    regarding: printf("PC: Now writing: "); this data will stay in the output stream until something happens (like another call to printf() that (properly) has a '\n' as part of the data (perferably the last character output) forces the data to be passed to the terminal Commented Jan 15, 2019 at 7:26
  • 1
    to call to read() will let the code know if anything is there to read. Waiting some arbitrary time is not a good method. Much better to keep calling ReadSerialPort() until some data is seen Commented Jan 15, 2019 at 7:28

1 Answer 1

1

Problem was in OpenSerialPort(). I set another variable fd which is local, thus given priority. then when OpenSerialPort() is done, it is deleted, and the global fd remain unset. This is why I can't send anything from or to the PC.

Thanks.

answered Jan 14, 2019 at 14:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.