Скорость последовательной передачи в бодах меньше указанной
Я хочу прочитать значения выводов arduino и отправить их на ПК через USB-кабель. Проблема в том, что запись/чтение байтов происходит со скоростью, которая примерно в 10 раз меньше скорости передачи данных последовательного порта.
Я записываю 8 символов в последовательный "abcdefgh", а затем println добавляет еще два символа "\r\n", так что это 10 байт на строку (я отдельно проверил, что время чтения линейно зависит от количества байтов в строке). Вот мой код arduino для случая заданной скорости передачи данных = 9600.
void setup() {
Serial.begin(9600);
}
void loop() {
for (char c ='a'; c < 'h'; c++)
Serial.print(c);
Serial.println('h');
}
Затем я использую python для чтения последовательного порта и измерения прошедшего времени (я также использовал Matlab и получил те же результаты).
import numpy as np
import serial
import time
ser = serial.Serial('COM5', 9600);
bytes_per_line = 10;
num_lines = 1000;
lines = np.empty(num_lines, dtype='|S11');
t0 = time.time()
for i in range(num_lines):
lines[i] = ser.readline();
t1 = time.time()
ser.close();
baud_calc = bytes_per_line*num_lines/(t1-t0);
Для указанной скорости передачи данных 9600 я измеряю только 837, я также тестирую скорость передачи данных 38400, 74880, 230400, 5e5, 1e6, 2e6 (я масштабирую количество строк для чтения со скоростью передачи данных так, чтобы общее чтение заняло ~10 секунд). Вы можете увидеть результат на графике ниже.
Легенда сюжета следующая:
- синий: измеренная скорость передачи данных в бодах
- красный: недостижимая идеальная скорость передачи данных (т. е. измеренная = указанная)
- черный: скорость передачи 230400 бод, которую я хотел бы достичь для своих приложений.
P.S. Причина, по которой я хочу, чтобы скорость передачи данных составляла 230400, заключается в том, что я считываю значения по кабелю GPIB и вижу, что данные, которые я измеряю, не соответствуют тому, что я знаю о протоколе GPIB. Если быть более точным, я вижу, что количество различных состояний GPIB-кабеля увеличивается, когда я увеличиваю скорость передачи данных.
@David Saykin, 👍2
Обсуждение1 ответ
Как указывает timemage, скорость передачи данных составляет биты в секунду. Поскольку формат кадра по умолчанию для последовательного порта использует 8 битов данных, 1 Начальный бит, 1 Стоп-бит и отсутствие четности, это составляет 10 бит на символ. Таким образом, теоретический предел при скорости 9600 Бод составляет 960 символов (или байт) в секунду. Если это передается в виде отдельных символов, как вы делаете это в своем примере, также добавляются некоторые накладные расходы на программное обеспечение, которые приведут к небольшому разрыву между передачей двух символов. Я бы предположил, что это около 10%. Имея это в виду, ваши измерения абсолютно разумны.
Чтобы повысить производительность, попробуйте изменить код arduino на
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("abcdefgh");
}
Это должно немного снизить накладные расходы и увеличить пропускную способность, чтобы вы приблизились к теоретическому пределу. Но достижение 230400 Байт/сек, вероятно, невозможно (я подозреваю, что "вмятина" в вашей кривой связана с приближением к другому ограничению, такому как скорость процессора).
Да, я определенно ошибся и перепутал байты и биты, но теперь, когда я обновляю свои измерения, они все еще не имеют для меня смысла. Например, теперь иногда измеренный бод становится больше, чем указанный бод., @David Saykin
@DavidSaykin Это странно. Можете ли вы поделиться своим обновленным графиком?, @PMF
Нет никаких накладных расходов на программное обеспечение. UART, передающий байты, и инструкции по обработке процессора выполняются _ параллельно_. Только при самых высоких скоростях передачи данных, когда UART начинает опустошать буфер TX быстрее, чем процессор может его заполнить, вы начинаете получать пробелы в передаче., @Edgar Bonet
Педантичное примечание: бод-это символ/секунда, а для двоичных данных бод эффективно соответствует биту/секунде., @Sacha
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- В чем разница между Serial.write и Serial.print? И когда они используются?
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Программы построения последовательных данных
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Очистить существующий массив при получении новой последовательной команды
Скорость передачи данных в битах в секунду или, по крайней мере, символ в секунду. С помощью начального бита и стоп-бита вы получаете байт на 10 последовательных битов. Это сюрприз или я что-то неправильно понял?, @timemage
@timemage да, это сюрприз. Спасибо. Я думаю, что мой вопрос глуп, и вы ответили на него. Я все еще не понимаю, почему мои показания недостаточно быстры для GPIB., @David Saykin
Ну, он, конечно, отформатирован и все такое. Если часть вопроса остается без ответа, вы всегда можете отредактировать его, чтобы удалить более тривиальную путаницу байт/бит и оставить вопрос о других частях., @timemage
Ваш метод измерения несовершенен. Во время записи " t0 " Arduino может сбросить настройки и начнет передачу только через некоторое время. Также очень вероятно, что в " t0 "буфер RX вашего компьютера уже заполнен, и первые вызовы" ser.readline()
просто считывают (очень быстро) этот буфер. Я предлагаю прочитать много килобайт, прежде чем записывать " t0
. Это гарантировало бы, что вы достигли устойчивого состояния. В установившемся режиме скорость приема должна соответствовать скорости передачи., @Edgar Bonet