Нет связи с подключенным последовательным портом? - PullRequest
0 голосов
/ 14 января 2019

Я пытаюсь подключиться к устройству 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, будет принята с благодарностью!

1 Ответ

0 голосов
/ 14 января 2019

Проблема была в OpenSerialPort(). Я установил другую переменную fd, которая является локальной, и, таким образом, получил приоритет. затем, когда OpenSerialPort() сделано, оно удаляется, а глобальное fd остается неустановленным. Вот почему я не могу ничего отправлять с или на ПК.

спасибо.

...