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!