Медленная операция чтения по 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, то потребуется еще секунда, чтобы выключить светодиоды.

Есть ли способ управлять светодиодами почти в режиме реального времени?

, 👍-1


4 ответа


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

2

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

В тех случаях, когда светодиодам требуется 1 секунда для реакции, вы, скорее всего, отправляете менее 3 байт, что приводит к тайм-ауту функции Serial.readBytes() после значения по умолчанию 1 секунда. Я предполагаю, что в настоящее время вы всегда отправляете только 1 байт (хотя вы пытаетесь прочитать 3 байта в своем коде).

Чтобы использовать символ-разделитель, существует несколько способов. Проще всего было бы использовать Serial.readStringUntil('\n'). Символ новой строки (который я использовал здесь в качестве параметра) является обычным символом-разделителем. Затем вам нужно будет всегда посылать символ новой строки в конце полного сообщения.

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


Кроме того: я действительно не понимаю, зачем вам нужно получать 3 байта для включения или выключения 3 светодиодов. Один байт (даже если вы используете только одиночные цифры) имеет достаточно большое пространство данных для большего количества этих 3 светодиодов. Кроме того, на самом деле вы не используете восьмеричные числа. atoi() ожидает строкового представления десятичного числа. В вашем коде нет ничего восьмеричного. А затем вы используете первые 3 бита полученного числа для управления светодиодами.

В общем, это кажется довольно сложным для очень простой задачи. Может быть, для этого есть какая-то причина, о которой вы не писали.

,

-1

Таким образом , проблема устраняется добавлением Serial.setTimeout(1) ; внутри setup (), который сообщает Serial.readBytes() ждать максимум 1 миллисекунду.

,

1

Вы вызываете функцию Serial.readBytes (), когда доступно или не доступно 3 байта. Если их нет, то вызов ждет их прибытия или тайм-аута. Это и есть задержка, которую вы видите.

Если вам действительно нужно 3 байта за раз, проверьте, есть ли их 3, прежде чем пытаться их прочитать:

if( Serial.available >= 3 )
   len = Serial.readBytes(buf, 3);

Когда if терпит неудачу - потому что нет доступных трех байтов - вы не будете тратить время на ожидание их.

,

0

На Arduino UNO контакты 0 и 1 используются для последовательной связи. Здесь это может и не иметь значения, но, вероятно, будет хорошей идеей избегать их, если только они действительно не нужны.

,

Это должен быть комментарий, @Sim Son