Два сериала не могут работать на одной скорости
У меня есть устройство, которое подключается к контактам 10/11 платы Arduino UNO. Я пытаюсь отправлять команды с моего ПК с помощью Arduino для передачи моих команд на устройство через последовательный порт.
Проблема в том, что если я использую скорость 9600 как для устройства, так и для связи по USB, мои команды будут повреждены. Некоторые буквы заменяются странными символами и т.д. Устройство использует скорость 9600 бод.
Если я изменю скорость связи с ПК на 4800 (или любую скорость, кроме 9600), все будет в порядке. Но мне приходится использовать разные скорости для связи.
Мне не нравится обходной путь, потому что я не понимаю, что происходит. Может ли кто-нибудь объяснить, почему одинаковые скорости последовательного порта вызывают проблемы?
Вот мой код:
#include <SoftwareSerial.h>
#define rxPin 11
#define txPin 10
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
void setup()
{
digitalWrite(4,HIGH); // 1 - отключить
mySerial.begin(9600);
Serial.begin(19200);
while (!Serial) {;} // ждем подключения последовательного порта. Требуется только для родного порта USB
Serial.println("Begin");
}
void loop()
{
if (mySerial.available())
{
char c = mySerial.read();
Serial.write(c);
}
if (Serial.available())
{
char c = Serial.read();
mySerial.write(c);
}
}
2 ответа
Если вы уверены, что устройство, которое вы подключили к Arduino Uno, имеет надежную прошивку для последовательной связи, вам может потребоваться некоторая буферизация перед ретрансляцией ваших команд;
#define RECORD_SIZE 100
void loop()
{
RelayDataIfAvaliable();
}
void RelayDataIfAvaliable() {
static char buffer[RECORD_SIZE];
if (Serial.available())
{
if (readline(Serial.read(), buffer, RECORD_SIZE) > 0) {
mySerial.write(buffer);
}
}
}
//Считывает все входящие данные в буфер один раз
int readline(int readch, char *buffer, int len)
{
static int pos = 0;//Изначально было равно нулю. Но в нем отсутствовал первый символ!
int rpos;
//Serial.print(readch);
if (readch > 0) {
switch (readch) {
case '\n': // Игнорировать новые строки
break;
case '\r': // Возврат по CR
rpos = pos;
pos = 0; // Сбросить индекс позиции, готовый к следующему разу
return rpos;
default:
if (pos < len - 1) {
buffer[pos++] = readch;
buffer[pos] = 0;
}
}
}
// Конец строки не найден, поэтому возвращаем -1.
return -1;
}
Я играл с этим подходом. Буферизованное чтение не помогает. Та же проблема: все нормально, пока не выставлю одинаковую скорость для обоих сериалов. Заказал Мегаборд. Это должно решить проблему наверняка. :) Большое спасибо!, @Konstantin Borisov
Но есть еще один путь, прежде чем идти по этой дороге. Когда я проверил это техническое описание двигателя, он также может обмениваться данными через I2C или SPI. Вы бы тоже так не думали? Например, этот образец выглядит довольно многообещающе: [демонстрация RMC220x] (https://github.com/wincelet/tuftsrobotics_icc2015/blob/master/rmcs2203_demo), @Sener
Ах, еще одно, вы проголосовали против моего ответа (работа в процессе)? это было единственное место, где я мог разместить отформатированную кодировку, поэтому я не обязательно давал окончательный ответ. Я считаю, что по крайней мере это заслуживает уважения., @Sener
нет, это не мой голос против. Я отметил ваш ответ как полезный. Так как мне не хватает репутации, она записывается, но не отображается. Ваши ответы мне очень помогают!, @Konstantin Borisov
Спасибо за ваш отзыв и отметку моего ответа. Удачи с вашим проектом., @Sener
Я провел некоторое время, играя с вашим кодом, и кажется, что ваш код на самом деле зацикливает последовательный порт, поэтому, если они оба установлены на 9600 в качестве примера, и вы печатаете то, что отправляет другой, как в вашем коде, вы в конечном итоге в цикле, если вы хотите прочитать, что отправляет ваш последовательный порт, лучше поместить эти значения в переменную и отправить
если вы загрузите свой код, вы получите следующее сообщение в IDE arduino при попытке подключения к последовательному монитору:
Ошибка при открытии последовательного порта COM8. (Порт занят),
ваш порт занят, потому что один последовательный порт все время считывает данные с другого
Еще одна вещь, которую я бы использовал, если вы хотите повторить последовательный порт:
if (mySerial.available())
{
//char c = mySerial.read();
Serial.write(mySerial.read());
}
Надеюсь, это поможет вам
- AT-команда не отвечает на последовательный монитор
- Как отправить команду AT на sim800l с помощью SoftwareSerial
- Ардуино для чтения с преобразователя RS232 в последовательный модуль TTL
- Чтение SMS с помощью Arduino Uno и SIM800L и печать на LCD (16x2 буквенно-цифровых) с использованием последовательного соединения
- Как связаться с ESP8266 ESP01, отправив данные через программный сериал на Arduino Uno?
- myserial.available() возвращает нулевой байт
- Последовательная связь от Arduino до ESP8266 NodeMCU работает, но от NodeMCU до Arduino не работает
- SoftwareSerial данные недоступны
SoftwareSerial не мой фаворит, и у меня не было хорошего вкуса с ним. Но, в любом случае, возможно, вы должны дать более подробную информацию об устройстве, которое вы подключаете к контактам 10 и 11., @Sener
@Sener Устройство представляет собой сервопривод RMCS 2201: Ссылка на спецификации Он имеет фиксированную скорость 9600 бод. Я подключил его напрямую к COM с помощью TTL-конвертера, и он отлично работает. Итак, я предполагаю, что где-то в моем коде есть проблема. Попробую ваш код буферизации. Спасибо ! Может подскажете чем заменить SoftwareSerial?, @Konstantin Borisov
Спасибо за подробную информацию об устройстве. Если он работает с модулем USB to TTL, то мы должны подумать о коде. Пожалуйста, попробуйте код, который я упомянул. И даже дальше, попробуйте вместо этого использовать аппаратный серийный номер., @Sener
Но Arduino Uno имеет только один аппаратный серийный номер с контактами 0: RX, 1: TX. Тогда вы не сможете использовать связь с ПК через USB. Вы также можете рассмотреть Arduino Mega с 4 последовательными портами., @Sener
Возможно прерывание от входящего байта что-то меняет в исходящем байте SoftwareSerial. Это возможно. Возможно, серводвигатель также имеет какой-то программный серийный номер и требует идеальной синхронизации последовательного сигнала. Чтобы избежать коллизий, вы можете сначала прочитать полную строку, как показывает ответ @Sener. Но вам лучше использовать аппаратный последовательный порт arduino mega или arduino leonardo., @Jot
Скорость серводвигателя может быть на несколько процентов выше или ниже. SoftwareSerial использует фиксированную скорость передачи данных, вы не можете это изменить. Аппаратный серийный номер вычисляет значение для регистра uart. Я думаю, что аппаратный серийный номер может установить немного другую скорость передачи данных., @Jot
@Jot, буферизованное чтение не помогло. Я заказал Мегу, чтобы решить эту проблему. Благодарю вас!, @Konstantin Borisov
@konstantin, можешь попробовать "понюхать" общение? Я имею в виду, когда связь продолжается, подключите провод RX USB TTL к контакту TX Arduino, затем к RX и проверьте, где связь повреждена., @frarugi87
Последовательное программное обеспечение работает только в полудуплексном режиме (вы не можете отправлять и получать одновременно). AltSoftSerial — очень хороший вариант. https://www.arduinolibraries.info/libraries/alt-soft-serial, @Dorian
Если вы используете UNO, то почему у вас есть эта строка: while (!Serial) {;}, которая даже в комментарии в вашем собственном коде говорит, что она не нужна для вашей платы?, @Delta_G