Я пытаюсь подключиться к устройству Arduino Mega 2560, подключенному через последовательный порт USB, к моему ПК на базе Linux.
Используя код C, я пытаюсь отправлять и получать простые текстовые строки, просто я могу отправлять и получать с обеих сторон.
На 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);
}
}
По сути, это просто цикл, который проверяет, есть ли последовательные данные, и если да, то читает их и печатает обратно. есть преобразование (char), поэтому я сразу увижу, что отправленные данные вернулись (сторона Linux)
Для кода Linux я использую довольно стандартный код для открытия порта, который я нашел здесь
Я называю Arduino «Таблицей», поскольку она в конечном итоге будет управлять движущимся столом с помощью команд USB.
C файл:
#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");
}
}
}
В OpenSerialPort
Я в основном открываю новый fd
и вызываю функции, которые устанавливают настройки связи.
Я использую PrepareWriteCommand
, чтобы убедиться, что команды, вводимые пользователями, имеют символ остановки, и отправлять их на WriteSerialPort
, где я использую write()
, и выводить количество отправленных байтов.
H файл:
#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
Я попытался изменить настройки флагов TTY, но безуспешно. Каждый раз, когда я запускаю код C, я вижу, что Arduino сбрасывается (и после открытия нового fd
я даю ему некоторое время для загрузки), но между ними не передается сообщение.
Выход:
PC: Opening port to table
PC: Connected
testPC: Now writing:
PC: Written 4 bytes
PC: received 0
PC:
Любая помощь в понимании того, почему код C не может связываться с Arduino, будет принята с благодарностью!