C: No communication to a connected serial port?

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;                  // 0.5 seconds read timeout
        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)
    {
        received = ReadSerialPort(output,MAX_DATA_LENGTH);//check serial port for response
        switch(received)
        {
            case -1:
            {
                printf("PC: Error %d from %s \n",errno, strerror(errno));
                break;
            }
            case 0:
            {
                printf("PC: Nothing received\n");
                usleep(500000);
                break;
            }
            default:
            {
                 printf("PC: received %i\n",received); //if yes, how many bytes
                printf("PC: %s\n",output); //and what was received
                usleep(500000);
            }
        }
    }
    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!

Can you post your Arduino program?

...R

Robin2:
Can you post your Arduino program?

...R

Thanks for replying!

Here it is:

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);
  }
 
}

edit:
I was noticed I didn't assign received in main function.
I changed in main to:

while(true)
    {
        received = ReadSerialPort(output,MAX_DATA_LENGTH);//check serial port for response
        switch(received)
        {
            case -1:
            {
                printf("PC: Error %d from %s \n",errno, strerror(errno));
                break;
            }
            case 0:
            {
                printf("PC: Nothing received\n");
                usleep(500000);
                break;
            }
            default:
            {
                 printf("PC: received %i\n",received); //if yes, how many bytes
                printf("PC: %s\n",output); //and what was received
                usleep(500000);
            }
        }
    }
    return 0; //finish program

output now:

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

PC: received 8
PC:

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.

Thanks for the update. Good to see you have found the problem.

...R