Вопрос или проблема
Я хочу напрямую мониторить соединение по последовательному интерфейсу через 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-принтера. Важно помнить, что низкоуровневые операции требуют административных прав, что следует учесть при выполнении данных действий.