последовательный канал связи с Arduino to raspberrypi

0

У меня возникли проблемы с символами мусора и странными данными, поступающими через последовательное соединение, которое я пытаюсь настроить между ардуином и raspi. Ардуино используется для сбора данных с разных датчиков и передает его в raspi как разделительную линию, однажды на "фрейм" (не идеально, но все же более чем достаточно быстро для моих нужд)

При использовании последовательного интерфейса arduino на моем компьютере с Windows или при использовании "sudo screen/dev/ttyACM0 115200, cs8" на raspberrypi данные проходят через штраф, поэтому я уверен, что ардуино не проблема.

У меня есть следующий код, чтобы установить соединение на стороне raspi:

int serial::openPort(std::string portName)
{
    int serialPort;

    serialPort = open(portName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);

    if (serialPort == -1)
    {
        std::cout << "open_port: Unable to open " << portName;
    }
    else
    {
        struct termios portOptions;

        //set up the port so reading nothing returns immediately, instead of blocking
        fcntl(serialPort, F_SETFL, FNDELAY);

        // Fetch the current port settings
        tcgetattr(serialPort, &portOptions);

        // Flush the port buffers (in and out) before we start using it
        tcflush(serialPort, TCIOFLUSH);

        // Set the input and output baud rates
        cfsetispeed(&portOptions, B115200);
        cfsetospeed(&portOptions, B115200);

        // c_cflag contains a few important things- CLOCAL and CREAD, to prevent
        //   this program from "owning" the port and to enable receipt of data.
        //   Also, it holds the settings for number of data bits, parity, stop bits,
        //   and hardware flow control. 
        portOptions.c_cflag |= CLOCAL;
        portOptions.c_cflag |= CREAD;
        // Set up the frame information.
        portOptions.c_cflag &= ~PARENB;
        portOptions.c_cflag &= ~CSTOPB;
        portOptions.c_cflag &= ~CSIZE;
        portOptions.c_cflag |= CS8;

        // Now that we've populated our options structure, let push it back to the
        //   system.
        tcsetattr(serialPort, TCSANOW, &portOptions);

        // Flush the buffer one more time.
        tcflush(serialPort, TCIOFLUSH);
    }

    return serialPort;
}

И следующее должно прочитать все данные в буфере:

std::string serial::readData(int serialPort)
{
    char buffer[64];
    int bytesRead = 0;
    std::string returnString;

    do
    {
        bytesRead = read(serialPort, buffer, sizeof(buffer));

        if(bytesRead > 0)
            returnString.append(buffer, bytesRead);

    } while (bytesRead == sizeof(buffer));

    return returnString;
}

который затем обрабатывается в этом цикле: (я использую только последний "фрейм" данных, которые поступают, потому что данные от arduino поступают намного быстрее, чем я могу отображать его на raspi)

gaugeDataBuffer += serial::readData(port);

std::cout << gaugeDataBuffer;

while(true)
{
    newLineLocation = gaugeDataBuffer.find("\r\n");

    if (newLineLocation == std::string::npos)
        break;

    gaugeDataStrings = utility::split(gaugeDataBuffer.substr(0, newLineLocation), ',');
    gaugeDataBuffer = gaugeDataBuffer.substr(newLineLocation + 2);
}

Проблема здесь, когда данные попадают на консоль (cout в последнем блоке кода), иногда это искажает. Я бы ожидал красивой упорядоченной серии строк данных, но иногда я получаю странные управляющие символы, буквы, строки данных, которые усекаются и т.д.

У меня такое ощущение, что это происходит во втором, чтобы последний блок кода, где я добавляю какие-либо новые данные в returnstring, но я не уверен, что это так, или как это исправить.

Любая помощь будет принята с благодарностью.

  • 0
    Я бы предположил, что последовательные порты правильно синхронизированы по фактической скорости передачи данных?
  • 0
    И arduino, и raspi используют скорость передачи данных 115200, и должны быть установлены как 8N1. Я немного не уверен, верно ли это для стороны распи, но все, что я прочитал, говорит о том, что я делаю это правильно.
Показать ещё 2 комментария
Теги:
arduino

3 ответа

0
Лучший ответ

как оказалось, изменение функции, которая извлекает данные:

std::string serial::readData(int serialPort)
{
    char buffer[1];
    int bytesRead = 0;
    std::string returnString;

    do
    {
        bytesRead = read(serialPort, buffer, 1);

        if(bytesRead > 0)
        {
            returnString += buffer[0];
        }

    } while (bytesRead == sizeof(buffer));

    return returnString;
}

похоже, устраняет проблему. Не уверен, что это идеальный, но он работает для меня.

0

Убедитесь, что ваши устройства говорят о том же напряжении. Я последовательно подключил Arduino к Pi с преобразователем уровня, потому что Pi - это устройство на 3,3 В, а Arduino - 5в.

Вот конвертер уровня: http://www.adafruit.com/product/757

  • 0
    они соединены через usb, насколько я понимаю, это не должно быть проблемой на USB-портах pi.
0

Простая связь по RS232 не является надежной связью. Даже если 2 устройства работают правильно, может произойти ошибка связи (из-за плохих проводов, паразитов,...). Вы должны добавить механизм, который позволяет, по крайней мере, обнаруживать плохие кадры (контрольная сумма, crc,...) и игнорировать их.

  • 0
    "паразиты"
  • 0
    У меня нет проблем с этим, используя команду screen, о которой я писал выше, на raspi, или используя стандартный последовательный монитор arduino на моем компьютере. У меня есть некоторый элементарный код для проверки длины строк ответа, но я не думаю, что должен видеть огромное расхождение между моим кодом и последовательным монитором, которым я являюсь в настоящее время.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню