Отправка данных аналогового датчика на ноутбук со скоростью 1 кГц через USB
Я читаю данные аналогового датчика с помощью Arduino nano, и требуемая частота дискретизации составляет около 1 кГц. Я использую пример AnalogReadSerial, предоставленный Arduino с задержкой 1 мс, поэтому я ожидаю получить около 1000 выборок в секунду или чуть меньше из-за задержки преобразования АЦП. Однако максимальное количество сэмплов, которые я могу получить в своем ноутбуке, чуть меньше 200 сэмплов в секунду. Я попытался увеличить скорость передачи данных до 115200, но это не помогло. Я что-то упускаю здесь, или мне нужно что-то сделать, чтобы получить мои данные с требуемой частотой дискретизации?
Ниже приведен код AnalogReadSerial, который я использовал для справки:
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(115200);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
delay(1); // delay in between reads for stability
}
@AmrSherbiny, 👍1
Обсуждение1 ответ
Лучший ответ:
Как я уже сказал в комментарии, ваш код на Uno дает мне 791,5 образцов/с. Это примерно 1263 мкс на образец:
- около 110 мкс для
analogRead()
, включая 104 мкс для собственно преобразования - предположительно 1000 мкс для
задержки(1)
- 153 мкс для остальной части кода, в основном форматирование
sensorValue
в ASCII
Согласно этим таймингам, если бы не вызов delay()
,
Arduino смог бы завершить цикл за одну миллисекунду и
все еще иметь в запасе 737 мкс. Самый простой способ добиться этого-
следовать стратегии Blink Without Delay:
void loop() {
static uint32_t last_conversion_time = micros();
if (micros() - last_conversion_time >= 1000) {
last_conversion_time += 1000;
Serial.println(analogRead(A0));
}
}
Это дает мне 1000 выборок в секунду. Обратите внимание, что
last_conversion_time
обновляется путем добавления 1000 мкс, а не
установки его в micros ()
, так что на самом деле это вариация мигания
Стратегия без промедления. Обновление last_conversion_time
таким образом
гарантирует, что всякий раз, когда программа опаздывает и пропускает нужную
микросекунду, небольшие ошибки синхронизации не накапливаются.
Для максимально возможной точности синхронизации было бы более целесообразно запускать АЦП по таймеру, но этот подход более сложен и требует тщательного чтения спецификации микроконтроллера.
Я бы не назвал это стратегией BlinkWithoutDelay. Это совсем другое дело. Было бы лучше инициализировать last_conversion_time с помощью micros (), чтобы ему не приходилось догонять 1 мс приращения времени, потерянного в setup() ., @Juraj
@Juraj: Я отредактировал ответ, чтобы учесть ваши комментарии. Обычно я предпочитаю, чтобы last_conversion_time
был инициализирован нулем, если только setup()
не работает очень медленно (не в данном случае): это экономит стоимость охранной переменной и теста на каждой итерации цикла. Но тогда, может быть, я слишком склонен к микрооптимизации..., @Edgar Bonet
- Управление ардуино через python
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- В чем разница между библиотеками Software Serial? Какая из них совместима с Arduino Nano?
- Как отправить команду AT на sim800l с помощью SoftwareSerial
- Проблемы с последовательной связью от Arduino к Bluetooth HC-05
- Как Arduino может проверить, подключен ли он к ПК и включен ли компьютер?
- Как отправлять и получать беззнаковые целые (unsigned int) от одного arduino к другому arduino
- Использование последовательных контактов TX/ RX для связи по USB
запишите значение
millis()
до и послеint sensorValue = analogRead(A0);
... затем выведите два значения, @jsotola@jsotola Я использовал micros(), и это занимает 116 микросекунд., @AmrSherbiny
115kBaud на самом деле должно быть достаточно. 1000 сообщений примерно по 6 байт каждое (4-значное число и CR/LF) используют 6000 байт или 60000 бит в секунду. Как быстро вы сможете это сделать, если уберете задержку?, @PMF
Запуск вашего кода на моем Uno дает мне 791,5 сэмплов/с. Может быть, ваш ноутбук слишком медленный, чтобы справиться со скоростью передачи данных?, @Edgar Bonet
Ошибка новичка от меня, мне пришлось соответствующим образом настроить скорость передачи данных USB-порта моего ноутбука, используя "ssty", потому что по умолчанию было 9600. Прямо сейчас я получаю данные со скоростью, аналогичной вашей @Edgar Bonet, которая лучше, но все еще немного стесняется требуемой скорости. @PMF ваши расчеты имеют смысл, и эта скорость должна быть в пределах моего ноутбука и Arduino nano, что все еще сбивает меня с толку. Я удалю задержку и проверю, имеет ли это какое-то значение., @AmrSherbiny
поскольку serial использует ascii, может быть меньше данных для отправки дельты между каждым чтением, чем целое число. например,
128,129,127
- это 11 символов,128,1, -2
- это только 8 символов., @dandavis