Какова лучшая задержка между символами, отправленными в последовательный порт

У меня есть Arduino Uno. Его роль заключается в том, чтобы эхом возвращать то, что он получает.
Но если я отправлю ему поток символов ascii, он начнет ошибаться после первого. Иногда он получает второй символ правильно, но часто нет.

Если я задерживаю каждый символ, то он работает нормально. Я не мог видеть это ограничение, упомянутое в библиотеке SoftwareSerial: https://www.arduino.cc/en/Reference/SoftwareSerial

Arduino работает со следующим кодом:

#define BT_RX_PIN 16 // A2
#define BT_TX_PIN 17 // A3
#include <SoftwareSerial.h>
SoftwareSerial OtherSerial(BT_RX_PIN, BT_TX_PIN);

void setup()
{
  Serial.begin(9600);  // not used
  OtherSerial.begin(9600);
}

void loop()
{
  if (OtherSerial.available()) {
    char value = OtherSerial.read();
    String stri = "Received: ";
    stri += value;
    OtherSerial.println(stri);
  }
}

Ограничения говорят: "При использовании нескольких последовательных портов программного обеспечения только один может получать данные одновременно". У меня нет нескольких последовательных портов программного обеспечения, хотя у меня есть экземпляр "обычного" последовательного порта, но я не отправляю в него никаких данных. .. но, возможно, даже просто инициализации достаточно, чтобы нарушить бесшовную связь с портом SoftwareSerial?

Используя следующий тестовый код для последовательной связи с Raspberry Pi (используя преобразование логического уровня для перехода от 5 В -> 3,3 В и наоборот):>

import time

def write(msg, delay):
  for char in msg:
    with open("/dev/ttyAMA0", "w") as f:
      f.write(char)
      time.sleep(delay)

write("hello", 0.01)

Я получил следующие результаты (повторенные 10 раз при каждом времени задержки и усредненные):

Delay (ms)   |   Success rate
10           |   100 %
9            |   100 %
8            |     0 %
5            |     0 %
1            |     0 %

Задержка 9 мс между каждым символом означает, что скорость связи падает от ~ 960 символов в секунду (9600 бод / 10 бит на 7 битный символ) до ~ 100 символов в секунду (1 / (1 / 960 символов в секунду + 9 мс)). Это правильно? Возможно, я делаю что-то еще неправильно / неправильно настраиваю его в программном / аппаратном обеспечении?

, 👍2

Обсуждение

На самом деле нет никакой "лучшей задержки", поскольку, по-видимому, необходимая задержка зависит от того, что RPi посылает Arduino. Чем больше передает RPi, тем больше задержка, чтобы Arduino не пропустил никаких данных., @st2000

Открываете ли вы последовательный порт для каждого отдельного символа? Почему? Не следует ли поставить строку " с "перед строкой "для"?, @Nick Gammon

@NickGammon это был быстрый взлом, чтобы сбросить символы в файл., @AJP

Быстрый взлом или нет, конечно, открытие файла каждый символ займет время?, @Nick Gammon

@NickGammon ах, вы имеете в виду с точки зрения создания значения "delay ms", о котором я сообщил здесь, на самом деле еще больше? Правда. Однако тот факт, что мы оперируем десятками мс, означает, что это, вероятно, несущественно. * выключается, чтобы проверить * похоже, что вы можете открыть и закрыть этот файловый дескриптор 180 раз за 10 миллисекунд на оборудовании, которое я использую, около 57 микросекунд., @AJP

Есть ли у вас оборудование для измерения фактической задержки между отправками? По моим расчетам, вам понадобится *более длинная* задержка: 13 * (1/960) = 13,54 мс, в то время как вы говорите, что он работает с задержкой 10 мс., @Nick Gammon

Вполне очевидно, что вы получите гораздо лучшую пропускную способность, если не будете отправлять слово "Received:" для каждого символа, который вы получаете. Это все равно, что каждую секунду класть в ведро 13 литров воды и вынимать 1 литр, а потом удивляться, почему она переполняется., @Nick Gammon

Спасибо за ваши мысли @NickGammon. Это в основном связано с поведением и ограничениями, которые не были четко описаны в документации, что я на stackexchance прошу о помощи., @AJP

В документации действительно должно быть ясно, что SoftwareSerial не может принимать одновременно с передачей, поэтому это не очень хороший выбор для попытки сделать это., @Nick Gammon


2 ответа


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

5

Программное обеспечение имеет значительные накладные расходы. Он часто может успешно отправлять на 115200, но 9600-это примерно его предел для приема, и вы пытаетесь одновременно отправлять и получать. Кроме того, для каждого символа, который получает ваш код, он передает значительно больше, чем 1 символ (11 символов, по моему подсчету). Неудивительно, что он отстал. Вам нужно будет либо уменьшить размер того, что вы передаете эхом, либо уменьшить скорость, с которой вы отправляете в него символы (что вы и сделали со своей задержкой), чтобы скорость передачи (эхо) могла сохраняться.

Обновление:

ОП сообщает об успехе с непрерывным приемом и передачей от Arduino на скорости 57600 бод (но не в одно и то же время). Скорость передачи будет соответствовать моему опыту передачи на скорости 115200 бод (вслепую и для коротких пакетов, чтобы перенастроить ESP8266-01, которые были отправлены с заданной скоростью 115200.

,

13 символов из-за возврата каретки/новой строки. Это правильно, вы не можете ожидать, что отправите 13 символов на каждый полученный вами, и не отставайте. Кроме того, когда SoftwareSerial отправляет, он отключается, поэтому не может принимать одновременно., @Nick Gammon

@JRobert Мне удалось успешно передавать непрерывно на скорости 57600 бод (но без передачи с Arduino до тех пор, пока на него не будет отправлено все сообщение). Не могли бы вы отредактировать свой ответ, чтобы отразить это, и я отмечу его как "правильный" ответ. Спасибо., @AJP

Конечно - это передача 57600 на - или с Arduino? Не имея прямого опыта, я чувствую, что должен процитировать ваш в своем обновлении., @JRobert

Да, передача 57600 осуществляется туда и обратно. Я попытался использовать 115200, но (и, возможно, это связано с моими более длинными электрическими проводами / отсутствием надлежащего заземления / помех), но это не сработало, и эхо было мусором. Это могла быть просто передача с Arduino на Raspberry Pi, но, несмотря на это, в данном случае она работала не на 115200, а на 57600., @AJP


5

Проще говоря, последовательный порт, реализованный в программном обеспечении, требует, чтобы программа достаточно быстро проверяла входной вывод, чтобы обнаруживать каждый переход. Чтобы удовлетворить частоте Найквиста, нам нужна программа, которая будет выполнять выборку данных в два раза быстрее, чем мы ожидаем, что данные изменятся.

Последовательный порт, реализованный аппаратно, может потребоваться только для выборки с 1/16 этой скорости, если размер данных составляет 8 бит.

Ваша программа реализует последовательный порт в программном обеспечении, которое превосходно соответствует полученным данным. Тем не менее, когда вы говорите программе, чтобы она отправила сообщение "Получено" плюс полученную строку, программа перестает смотреть на вывод последовательного ввода достаточно долго, чтобы данные пропали без вести.

Безусловно, самым простым решением было бы использовать аппаратно реализованный последовательный порт. Если это невозможно, рассмотрите возможность решения проблемы с помощью прерываний. Однако, будучи мощным инструментом программирования, прерывания могут быть трудно реализуемы и трудно отлаживаемы.

,