Как мониторить последовательное соединение на скорости 250000 бод?

Вопрос или проблема

Я хочу напрямую мониторить соединение по последовательному интерфейсу через USB с моим 3D-принтером, которое работает на скорости 250000 бод. Например, я могу мониторить его с помощью cat /dev/ttyUSB0

Но сначала мне нужно установить скорость передачи, например stty -F /dev/ttyUSB0 115200

Но если я попытаюсь установить скорость 250k, это не удается:

stty -F /dev/ttyUSB0 250000

возвращает результат:

stty: недопустимый аргумент 250000

Похоже, что скорость 250000 бод не поддерживается в Ubuntu/Mint. Может кто-нибудь предложить альтернативный способ мониторинга этого последовательного соединения?

Существуют некоторые незафиксированные ioctls, которые вы можете использовать для установки нестандартных скоростей, если драйвер их реализует. Простой способ вызвать их — с помощью небольшого куска кода на Python. Например, положите в файл mysetbaud.py и задайте ему исполняемые права с помощью chmod +x:

#!/usr/bin/python
# установка нестандартной скорости. http://unix.stackexchange.com/a/327366/119298
import sys,array,fcntl

# из /usr/lib/python2.7/site-packages/serial/serialposix.py
# /usr/include/asm-generic/termbits.h для структуры termios2
#  [2]c_cflag [9]c_ispeed [10]c_ospeed
def set_special_baudrate(fd, baudrate):
    TCGETS2 = 0x802C542A
    TCSETS2 = 0x402C542B
    BOTHER = 0o010000
    CBAUD = 0o010017
    buf = array.array('i', [0] * 64) # на самом деле 44
    fcntl.ioctl(fd, TCGETS2, buf)
    buf[2] &= ~CBAUD
    buf[2] |= BOTHER
    buf[9] = buf[10] = baudrate
    assert(fcntl.ioctl(fd, TCSETS2, buf)==0)
    fcntl.ioctl(fd, TCGETS2, buf)
    if buf[9]!=baudrate or buf[10]!=baudrate:
        print("не удалось. скорость %d %d" % (buf[9],buf[10]))
        sys.exit(1)

set_special_baudrate(0, int(sys.argv[1]))

Это использует некоторый код из пакета pyserial с константами для различных значений, необходимых из файлов заголовков C Linux, и массив для struct termios2. Вы используете его с параметром скорости и вашим устройством на стандартном вводе, например, из bash:

./mysetbaud.py <>/dev/ttyUSB0 250000

setserial -a /dev/ttyUSB0 spd_cust
setserial -a /dev/ttyUSB0 divisor 96

Теперь установите порт на 38400, чтобы получить 250000

stty -F /dev/ttyUSB0 38400

(или используйте его как 38400 в приложении, например, ser2net)

Я получил информацию с http://www.linurs.org/linux/SerialPort.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <asm-generic/termbits.h>

void set_special_baudrate(int fd, int baudrate) {
    struct termios2 tio;

    if (ioctl(fd, TCGETS2, &tio) != 0) {
        perror("ioctl(TCGETS2) не удался");
        exit(1);
    }

    tio.c_cflag &= ~CBAUD;
    tio.c_cflag |= BOTHER;
    tio.c_ispeed = tio.c_ospeed = baudrate;

    if (ioctl(fd, TCSETS2, &tio) != 0) {
        perror("ioctl(TCSETS2) не удался");
        exit(1);
    }

    if (ioctl(fd, TCGETS2, &tio) != 0) {
        perror("ioctl(TCGETS2) проверка не удалась");
        exit(1);
    }

    if (tio.c_ispeed != baudrate || tio.c_ospeed != baudrate) {
        fprintf(stderr, "не удалось. скорость %d %d\n", tio.c_ispeed, tio.c_ospeed);
        exit(1);
    }
}

void check_and_setuid() {
    if (getuid() != 0) {
        fprintf(stderr, "Не запущено от имени root. Пытаюсь установить uid...\n");
        if (setuid(0) != 0) {
            perror("setuid не удался");
            exit(1);
        }
    }
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Использование: %s <baudrate> <tty>\n", argv[0]);
        return 1;
    }

    int baudrate = atoi(argv[1]);
    char *tty = argv[2];

    check_and_setuid();

    int fd = open(tty, O_RDWR | O_NOCTTY);
    if (fd == -1) {
        perror("open не удался");
        return 1;
    }

    set_special_baudrate(fd, baudrate);

    if (close(fd) != 0) {
        perror("close не удался");
        return 1;
    }

    return 0;
}

Компиляция:

$ gcc -O3 setbaud.c -o setbaud -Wl,-s

Пример:

$ sudo ./setbaud 20000 /dev/ttyUSB0
$ sudo ./setbaud 30000 /dev/ttyUSB0
$ sudo ./setbaud 50000 /dev/ttyUSB0
$ sudo ./setbaud 250000 /dev/ttyUSB0

и так далее…

Ответ или решение

Как контролировать последовательное соединение на скорости 250000 бод

Если вы хотите следить за последовательным соединением через USB к вашему 3D-принтеру со скоростью 250000 бод, потребуется несколько шагов для настройки соединения. Обычно такие скорости не поддерживаются напрямую в стандартных утилитах, таких как stty. В данном руководстве мы рассмотрим, какие альтернативные методы можно использовать для достижения данной цели.

1. Настройка скорости порта

Для начала вам необходимо попытаться настроить скорость порта. Обычно, попытка задать скорость 250000 бод с помощью команды:

stty -F /dev/ttyUSB0 250000

выдаст ошибку, если установленная операционная система, например Ubuntu или Mint, не поддерживает этот параметр. Чтобы обойти это ограничение, можно использовать специальные системные вызовы через Python или C.

2. Использование Python для установки нестандартной скорости

Вы можете воспользоваться небольшим скриптом на Python, который позволит устанавливать нестандартные скорости для последовательных соединений. Вот пример такого скрипта:

#!/usr/bin/python
import sys
import array
import fcntl

def set_special_baudrate(fd, baudrate):
    TCGETS2 = 0x802C542A
    TCSETS2 = 0x402C542B
    BOTHER = 0o010000
    CBAUD = 0o010017
    buf = array.array('i', [0] * 64)
    fcntl.ioctl(fd, TCGETS2, buf)
    buf[2] &= ~CBAUD
    buf[2] |= BOTHER
    buf[9] = buf[10] = baudrate
    assert(fcntl.ioctl(fd, TCSETS2, buf) == 0)
    fcntl.ioctl(fd, TCGETS2, buf)
    if buf[9] != baudrate or buf[10] != baudrate:
        print("failed. speed is %d %d" % (buf[9], buf[10]))
        sys.exit(1)

set_special_baudrate(0, int(sys.argv[1]))

Сохраните этот код в файл mysetbaud.py, затем сделайте его исполняемым:

chmod +x mysetbaud.py

Для установки скорости 250000 бод выполните следующую команду:

./mysetbaud.py < /dev/ttyUSB0 250000

3. Использование C для низкоуровневого доступа

Если вы предпочитаете язык C, вот другой метод, чтобы установить скорость последовательного порта:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <asm-generic/termbits.h>

void set_special_baudrate(int fd, int baudrate) {
    struct termios2 tio;
    ioctl(fd, TCGETS2, &tio);
    tio.c_cflag &= ~CBAUD;
    tio.c_cflag |= BOTHER;
    tio.c_ispeed = tio.c_ospeed = baudrate;
    ioctl(fd, TCSETS2, &tio);
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <baudrate> <tty>\n", argv[0]);
        return 1;
    }
    int baudrate = atoi(argv[1]);
    char *tty = argv[2];
    int fd = open(tty, O_RDWR | O_NOCTTY);
    set_special_baudrate(fd, baudrate);
    close(fd);
    return 0;
}

Скомпилируйте программу:

gcc -o setbaud setbaud.c

Запустите её с параметрами:

sudo ./setbaud 250000 /dev/ttyUSB0

4. Мониторинг данных

После успешной настройки порта для работы на скорости 250000 бод, вы можете использовать стандартные утилиты, такие как cat, для мониторинга данных:

cat /dev/ttyUSB0

Дополнительно вы можете использовать более сложные инструменты, такие как screen или minicom, которые предоставляют более удобный интерфейс для работы с последовательными соединениями.

Заключение

Мониторинг последовательного соединения на скорости 250000 бод может требовать нестандартных решений. С помощью представленных выше методов вы сможете обходить ограничения стандартных утилит и получать доступ к потокам данных с вашего 3D-принтера. Важно помнить, что низкоуровневые операции требуют административных прав, что следует учесть при выполнении данных действий.

Оцените материал
Добавить комментарий

Капча загружается...