Отправлять одни и те же данные телеметрии на два разных последовательных порта?
Я использую Teensy 3.5 для управления роботом,следующим за стеной. Робот отправляет телеметрию на мой компьютер через два независимых порта - Serial1 и Serial. Serial-это обычный USB-порт, используемый при прямом подключении к роботу для устранения неполадок и т. Д. Serial1 привязан к приемопередатчику Bluetooth HC-05 и используется для удаленного получения телеметрии.
Я должен посылать телеметрию на оба порта, потому что я никогда не знаю, какой (или один, или оба) порта(порта) на самом деле активны в любой момент времени, поэтому я заканчиваю с такими строками по всему моему коду:
Serial.printf("\nChecking for MPU6050 IMU at I2C Addr 0x%x\n", MPU6050_I2C_ADDR);
Serial1.printf("\nChecking for MPU6050 IMU at I2C Addr 0x%x\n", MPU6050_I2C_ADDR);
излишне говорить, что через некоторое время это устареет и подвержено ошибкам (я могу отредактировать одну строку и забыть скопировать/вставить ее в другую). То, что я действительно хотел бы сделать, это создать функцию, которая будет принимать строку в стиле printf и отправлять ее на оба порта, но мне трудно понять, как это сделать.
Я попытался поиграть с strcpy и strcat без особого успеха:
char quotestr[] = "\"";
char hellostr[] = "hello";
char instr[] = "%s\n, hellostr";
char deststr[40];
memset(deststr, 0, sizeof(deststr));
strcat(deststr, quotestr);
strcat(deststr, instr);
strcat(deststr, quotestr);
Serial.printf("quotestr = %s\n", quotestr);
Serial.printf("instr = %s\n", instr);
Serial.printf("deststr = %s\n", deststr);
Serial.printf(deststr);
Но вывод неверен, потому что '\n' интерпретируется как пара CRLF, даже если она находится в строке с двойными кавычками.
quotestr = "
instr = %s
, hellostr
deststr = "%s
, hellostr"
"
, hellostr"
Кажется, должен быть способ сделать это легко, но я не могу понять. Любая помощь будет оценена по достоинству.
ТИА,
Фрэнк
@user3765883, 👍-1
Обсуждение2 ответа
вы можете написать простой вывод T, используя базовый класс Print
. Стандартный класс печати Arduino не имеет
printf
, но из вашего кода похоже, что ядро Teense имеет printf
в печати
.
class TeePrint: public Print {
Print &out1;
Print &out2;
public:
TeePrint(Print &_out1, Print &_out2) : out1(_out1), out2(_out2) {}
virtual size_t write(uint8_t b) {
out1.write(b);
out2.write(b);
return 1;
}
};
TeePrint log(Serial, Serial1);
void setup() {
Serial.begin(115200);
Serial1.begin(9600);
log.printf("abcd %d %s", 1234, "xyz");
}
void loop() {
}
Спасибо - ваш класс TeePrint очень элегантен. Одна незначительная гнида - он отказался компилироваться для T3.2, потому что " log " был объявлен в math.h. Когда я перешел с "log" на "myTee", все работало нормально, @user3765883
Самый простой метод - это вариационный макрос:
#define PRINTF(...) do { Serial.printf(__VA_ARGS__); Serial1.printf(__VA_ARGS__); } while(0)
Затем вы можете просто использовать PRINTF("foo: %d", bar);
и он расширит его до двух printfs для вас.
Это приведет к сбою в if (bar) PRINTF("foo: %d", bar);
. Вот почему люди используют идиому do {...} while (0)
., @Edgar Bonet
@EdgarBonet Я подумывал о том, чтобы добавить " {}", но не стал утруждаться. Я должен был это сделать. Теперь я это сделал. Do и while не нужны., @Majenko
Do
и while (0)
необходимы для `if (bar) PRINTF(...); else ...- работать, как положено., @Edgar Bonet
@EdgarBonet Нет, вам нужно только {} для этого., @Majenko
Это неверно. Попробуй!, @Edgar Bonet
Разве это не будет отображать выходную строку дважды? Это может иметь огромное значение, если пользователь хочет печатать сложные вещи, особенно если речь идет о поплавках., @luni64
@EdgarBonet Я делаю это регулярно. Я никогда не использовал и даже не видел конструкцию do while., @Majenko
@luni64 да, это так, но на крошечном это не будет заметно, так как они намного быстрее, чем Arduino., @Majenko
Без do
и while (0)
, if (bar) PRINTF(...); else ...
дает’ошибку: "else" без предыдущего "if". Попробуй, серьезно! Конструкция do {...} while (0)
является стандартным решением этой проблемы, и это [очень распространенная идиома](https://www.google.com/search?q=C+macro+do+while+0)., @Edgar Bonet
@EdgarBonet Ах, это будет тот факт, что вы добавили a ; после макроса, когда вы его использовали. Не делать этого?, @Majenko
Если вы не забудете _not_ добавить конечную точку с запятой после макроса, то это сработает. Но это сбивает с толку, так как макрос внешне выглядит как функция, но он должен использоваться с другим синтаксисом. Не могли бы вы воздержаться от добавления точки с запятой после getc ()
, потому что [это может быть реализовано как макрос](https://man7.org/linux/man-pages/man3/getc.3p.html)?, @Edgar Bonet
@EdgarBonet Тот факт, что все это написано заглавными буквами, свидетельствует о том, что это макрос. Такова условность. Конечно, если вы хотите добавить do while вокруг него, то do (while). Это не в моем стиле кодирования, так что я этого не делаю. Я пишу имена своих макросов заглавными буквами, чтобы помнить, что это макросы, и мне не нужно ; после них. Стиль кодирования каждого человека уникален., @Majenko
“Стиль кодирования каждого человека уникален” - это не оправдание того, что он сбивает с толку. Вы попали в свою собственную ловушку, так как случайно добавили точку с запятой в первых двух версиях этого ответа. Представьте себе, как легко кто-то другой, использующий определенный вами макрос, может попасть в эту ловушку., @Edgar Bonet
@EdgarBonet Если это заткнет тебе рот, я добавлю это. Хотя лично я им до сих пор не пользуюсь., @Majenko
- Как прервать соединение HM10 Bluetooth?
- Последовательная связь между Teensy и Teensy через USB-разъем
- Скорость передачи устанавливается на 9600 автоматически, даже если указано другое значение.
- Модуль SIM800L просто повторяет данные, отправленные через последовательный порт.
- Нет ответа от прибора по последовательной связи
- Почему я не могу использовать Jeelib Sleepy на Teensy 2 вместе с serial
- Teensy 4.1 последовательная связь с 7N2 (7 databits no parity 2 stopbits)
- Как определить, какая скорость передачи данных установлена для виртуального COM-порта?
\n
интерпретируется как новая строка, как это обычно бывает для ОС на базе Linux. Я бы сказал, что он делает именно то, что вы ему велели. Где ты на это смотришь? Почему это проблема? А вы думали об использованииsprintf()
для построения строки в массив char, который затем можно распечатать на обоих последовательных интерфейсах?, @chrislесли вам не нужна новая строка, удалите \n из строки, @Juraj
Использование
\\n
вместо\n
должно сделать свое дело., @Peter Paul Kiefer