Проблемы со чтением чисел из последовательного порта

Я создал 2 драйвера двигателей для проекта робототехники, и мне нужно установить положения, в которые я хочу, чтобы двигатели перемещались, и прочитать это с помощью Arduino. Затем Arduino использует поворотный энкодер для реализации ПИД-регулятора с обратной связью и перемещения двигателя на заданное значение. Мой код не работал, поэтому я начал устранять неполадки и обнаружил, что моя уставка автоматически сбрасывается на 0!

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

volatile long setpoint;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()){
    setpoint = Serial.parseInt();
    Serial.print("Set to: ");
    Serial.println(setpoint);
  }
}

Результат был довольно странным, он устанавливает значение правильно, но сбрасывает обратно на 0 без отправки каких-либо новых команд!

Я пытался обновить IDE до версии 1.8.12, пробовал старую и новую Arduino (со старым и новым загрузчиком), но у всех был один и тот же результат. Вот демонстрационное видео, показывающее странную проблему сброса до 0:

https://streamable.com/kfgv61

Я пытался увеличить или уменьшить скорость передачи данных, но это тоже ничего не исправило. Есть идеи, что я делаю не так?

, 👍0


1 ответ


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

1

Проблема в том, что Serial.parseInt() останавливается, когда видит новой строки, но не использует новую строку, оставшуюся в входной буфер. Таким образом, на следующей итерации цикла Serial.available() возвращает true из-за этой новой строки и, если вы не отправите другое значение достаточно быстро, Serial.parseInt() истекает и возвращает ноль.

Простое решение — использовать эту новую строку самостоятельно:

void loop() {
  if (Serial.available()){
    setpoint = Serial.parseInt();
    if (Serial.peek() == '\n') Serial.read();  // потребляем LF
    Serial.print("Set to: ");
    Serial.println(setpoint);
  }
}

Лично я вообще не стал бы использовать Serial.parseInt() и предпочел бы буферизировать данные самостоятельно, пока не увижу '\n'. Таким образом, есть никаких сюрпризов, когда тайм-ауты считываются как нулевые.

,