Медленная операция чтения по USB
Сегодня у меня есть Arduino UNO, и я как раз пишу базовую программу blink. У меня есть 3 светодиода на arduino. Эти светодиоды подключены к контактам 1, 2 и 3.
Теперь я могу управлять ими, записывая восьмеричные значения от 0 до 7 в /dev/ttyUSB0
.
Код, который я написал до сих пор:
# pragma GCC optimize ("Ofast")
# define LED1 1
# define LED2 2
# define LED3 3
char buf[4] ;
unsigned char inp, len ;
void setup() {
pinMode(LED1, OUTPUT) ;
pinMode(LED2, OUTPUT) ;
pinMode(LED3, OUTPUT) ;
Serial.begin(9600) ;
}
void loop() {
len = Serial.readBytes(buf, 3) ;
if (len) {
buf[3] = '\0' ;
inp = atoi(buf) ;
// Illuminate LEDs
digitalWrite(LED1, 1 & inp ? HIGH : LOW) ;
digitalWrite(LED2, 2 & inp ? HIGH : LOW) ;
digitalWrite(LED3, 4 & inp ? HIGH : LOW) ;
}
}
Поэтому, когда я пишу:
- 0 выключает все светодиоды
- 1 включает светодиод на выводе 1
- 2 включает светодиод на выводе 2
- 3 включает светодиод на контактах 1 и 2
- 4 включает светодиод на выводе 3
- 5 включает светодиод на контактах 1 и 3
- 6 включает светодиод на контактах 2 и 3
- 7 включает все светодиоды.
Проблема в том, что, например, когда я пишу 7, включение светодиодов занимает до 1 секунды. Если я напишу 0, то потребуется еще секунда, чтобы выключить светодиоды.
Есть ли способ управлять светодиодами почти в режиме реального времени?
@S.Goswami, 👍-1
4 ответа
Лучший ответ:
При отправке нескольких байтов, которые вместе образуют единое сообщение, лучше всего использовать символ-разделитель и читать данные до тех пор, пока они не появятся. Таким образом, вы не столкнетесь с тайм-аутами и можете быть уверены, что полученные данные представляют собой полное сообщение.
В тех случаях, когда светодиодам требуется 1 секунда для реакции, вы, скорее всего, отправляете менее 3 байт, что приводит к тайм-ауту функции Serial.readBytes() после значения по умолчанию 1 секунда. Я предполагаю, что в настоящее время вы всегда отправляете только 1 байт (хотя вы пытаетесь прочитать 3 байта в своем коде).
Чтобы использовать символ-разделитель, существует несколько способов. Проще всего было бы использовать Serial.readStringUntil('\n')
. Символ новой строки (который я использовал здесь в качестве параметра) является обычным символом-разделителем. Затем вам нужно будет всегда посылать символ новой строки в конце полного сообщения.
Просто установить очень низкий тайм - аут-не очень хорошее решение. При такой низкой скорости передачи данных, как 9600, это легко может означать, что сообщение разбито на несколько частей, потому что передача занимает больше времени, чем тайм-аут.
Кроме того: я действительно не понимаю, зачем вам нужно получать 3 байта для включения или выключения 3 светодиодов. Один байт (даже если вы используете только одиночные цифры) имеет достаточно большое пространство данных для большего количества этих 3 светодиодов. Кроме того, на самом деле вы не используете восьмеричные числа. atoi()
ожидает строкового представления десятичного числа. В вашем коде нет ничего восьмеричного. А затем вы используете первые 3 бита полученного числа для управления светодиодами.
В общем, это кажется довольно сложным для очень простой задачи. Может быть, для этого есть какая-то причина, о которой вы не писали.
Таким образом , проблема устраняется добавлением Serial.setTimeout(1) ;
внутри setup ()
, который сообщает Serial.readBytes() ждать максимум 1 миллисекунду.
Вы вызываете функцию Serial.readBytes ()
, когда доступно или не доступно 3 байта. Если их нет, то вызов ждет их прибытия или тайм-аута. Это и есть задержка, которую вы видите.
Если вам действительно нужно 3 байта за раз, проверьте, есть ли их 3, прежде чем пытаться их прочитать:
if( Serial.available >= 3 )
len = Serial.readBytes(buf, 3);
Когда if
терпит неудачу - потому что нет доступных трех байтов - вы не будете тратить время на ожидание их.
На Arduino UNO контакты 0 и 1 используются для последовательной связи. Здесь это может и не иметь значения, но, вероятно, будет хорошей идеей избегать их, если только они действительно не нужны.
- Несколько условий оператора if
- Светодиоды: разница между общим анодом и общим катодом
- Остановить мигание светодиодов
- Интеграция 2 кнопок для включения и выключения светодиода.
- Управление цифровой адресной светодиодной лентой RGB 12 В с помощью Arduino
- Код Arduino для управления 4 светодиодами с 4 кнопок
- Нужен ли подтягивающий/понижающий резистор для цепи светодиода кнопки?
- Мигните светодиодом 5 раз с помощью цикла for
Это должен быть комментарий, @Sim Son